如何使用jQuery检测移动设备

1946

有没有一种方法可以在jQuery中检测用户是否使用移动设备?类似于CSS的 @media 属性?如果浏览器在手持设备上,则我想运行不同的脚本。

jQuery的$.browser函数并不是我要找的内容。


8
为移动设备提供专门的移动设备URL。这是大多数主要网站处理移动设备的方式。请参见http://m.google.com。 - user229044
6
jQuery不能做所有的事情,它提供了跨浏览器的DOM遍历和操作、简单的动画和浏览器之间的ajax,并创建了插件开发的框架。在要求jQuery解决方案之前,请注意jQuery的局限性。 - Yi Jiang
87
用户代理是不断变化的目标,阅读本帖的所有人都应该非常警惕用户代理嗅探。 - Rob
57
什么是“移动”设备?它是否支持触摸(包括Chrome Pixel和带鼠标的Windows 8笔记本电脑)?它是否是具有小屏幕的设备(那么视网膜iPad呢)?它是否具有较慢的CPU?还是具有较慢的互联网连接?根据你想要做什么,答案会有所不同。针对屏幕分辨率或触摸进行定位很容易。如果您想为某些设备提供较小的内容或更少的JS,则没有银弹可言。测试window.navigator.connection并退回到(恶劣,不良,不建议)userAgent嗅探。以上仅代表个人意见。 - David Gilbertson
6
我明白你的意思。'手机'似乎被用作触摸、慢速CPU、慢速网络和小屏幕的总称。但是,这些都不是完美的假设。我认为单独考虑这些因素将比为某种模糊的“移动”概念而设计会得到更好的产品。因此,我向原帖发出那个问题。 - David Gilbertson
显示剩余12条评论
66个回答

19

你不能完全依赖于 navigator.userAgent,因为不是每个设备都会透露它真实的操作系统。例如,在我的HTC上,它取决于设置("使用移动版" 开/关)。 在 http://my.clockodo.com 上,我们简单地使用 screen.width 来检测小型设备。不幸的是,在一些Android版本中,screen.width 存在一个bug。你可以将这种方式与userAgent组合使用:

if(screen.width < 500 ||
 navigator.userAgent.match(/Android/i) ||
 navigator.userAgent.match(/webOS/i) ||
 navigator.userAgent.match(/iPhone/i) ||
 navigator.userAgent.match(/iPod/i)) {
alert("This is a mobile device");
}

10
许多手机的宽度超过1000,特别是在横屏模式下。 - oriadam

16
如果您使用Modernizr,那么像之前提到的那样使用Modernizr.touch非常容易。
但是,为了保险起见,我更喜欢同时使用Modernizr.touch和用户代理测试。
var deviceAgent = navigator.userAgent.toLowerCase();

var isTouchDevice = Modernizr.touch || 
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/)  || 
deviceAgent.match(/(iemobile)/) || 
deviceAgent.match(/iphone/i) || 
deviceAgent.match(/ipad/i) || 
deviceAgent.match(/ipod/i) || 
deviceAgent.match(/blackberry/i) || 
deviceAgent.match(/bada/i));

if (isTouchDevice) {
        //Do something touchy
    } else {
        //Can't touch this
    }

如果您不使用Modernizr,可以将上面的Modernizr.touch函数替换为('ontouchstart' in document.documentElement)
还要注意,测试用户代理iemobile将为您提供比Windows Phone更广泛的检测到的Microsoft移动设备范围。 此外,请参阅此SO问题。

在Dart中也是一样的:TouchEvent.supported - Kai Sellgren
('ontouchstart' in window)Modernizr.touch 的另一种选择,可以参考 https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how/。 - JVE999
你应该使用正则表达式中的 | 来代替多个匹配。由于你使用了 i 修饰符,所以你不需要使用 toLowerCase()。这里是代码: var isTouchDevice = Modernizr.touch || /iphone|ipod|ipad|android|iemobile|iphone|ipad|ipod|blackberry|bada/i.test(navigator.userAgent); - oriadam

14

我很惊讶没有人指出一个不错的网站:http://detectmobilebrowsers.com/。它提供了多种语言的代码用于检测移动设备(包括但不限于):

  • Apache
  • ASP
  • C#
  • IIS
  • JavaScript
  • NGINX
  • PHP
  • Perl
  • Python
  • Rails

如果您需要检测平板电脑,只需查看 "About" 部分以获取额外的正则参数。

Android 平板电脑、iPad、Kindle Fire 和 PlayBook 不会被默认检测到。要添加对平板电脑的支持,请在第一个正则表达式中添加 |android|ipad|playbook|silk


对我来说它是可以工作的,你能更具体地说明你使用了哪些代码以及问题出在哪里吗? - Maksim Luzik
那个页面是响应的,其他所有响应都是该页面的复制粘贴。 - Rubén Ruíz
这些可能已经过时了(尽管我还没有验证),因为当我访问它时,该网站显示:“Regex更新于2014年8月1日”。 - Greg

12

发现仅检查navigator.userAgent不总是可靠的。通过检查navigator.platform也可以获得更高的可靠性。对先前答案的简单修改似乎效果更好:

if (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ||
   (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.platform))) {
    // some code...
}

12
如果您不太担心小屏幕,可以使用宽度/高度检测。这样,如果宽度小于某个尺寸,则会显示移动站点。这可能并不是最完美的方法,但对于多个设备来说,这可能是最容易检测的方式。您可能需要为iPhone 4(大分辨率)添加特定的检测。

9

谢谢你的回答。为支持Windows Phone和Zune,需要进行小改进:

if (navigator.userAgent.match(/Android/i) ||
  navigator.userAgent.match(/webOS/i) ||
  navigator.userAgent.match(/iPhone/i) ||
  navigator.userAgent.match(/iPad/i) ||
  navigator.userAgent.match(/iPod/i) ||
  navigator.userAgent.match(/BlackBerry/) ||
  navigator.userAgent.match(/Windows Phone/i) ||
  navigator.userAgent.match(/ZuneWP7/i)
) {
  // some code
  self.location = "top.htm";
}

如果你想要处理移动设备的hover/dragging事件,我会说这是最简单的(也许不是最好的)解决方法。我使用类似这样的方式来创建一个"isMobile"布尔值,然后检查每个hover/mouseover事件。这只是我的个人看法。 对我来说,添加更多需要用户交互的js库或代码并不太有意义;如果我错了,请纠正我。 - MeanMatt
5
由于您正在使用正则表达式,实际上应该使用它们:if (navigator.userAgent.match(/Android|webOS|iPhone|iPad|etc/)){self.location = "top.htm"} - foobarbecue

9
为了增加额外的控制层,我使用HTML5存储来检测它是否正在使用移动存储或桌面存储。如果浏览器不支持存储,我有一个移动浏览器名称的数组,并将用户代理与数组中的浏览器进行比较。
这很简单。以下是函数:
// Used to detect whether the users browser is an mobile browser
function isMobile() {
    ///<summary>Detecting whether the browser is a mobile browser or desktop browser</summary>
    ///<returns>A boolean value indicating whether the browser is a mobile browser or not</returns>

    if (sessionStorage.desktop) // desktop storage 
        return false;
    else if (localStorage.mobile) // mobile storage
        return true;

    // alternative
    mobile = ['iphone','ipad','android','blackberry','nokia','opera mini','windows mobile','windows phone','iemobile','tablet','mobi']; 
    var ua=navigator.userAgent.toLowerCase();
    for (var i in mobile) if (ua.indexOf(mobile[i]) > -1) return true;

    // nothing found.. assume desktop
    return false;
}

1
你基于localStorage的假设很有趣,能否提供一些支持你脚本的设备或浏览器范围?我对我所提出的这个问题的解决方案很感兴趣,尝试检测移动平板电脑浏览器确实是一个有趣的解决方法。 - Gruber

9

我建议你查看http://wurfl.io/

简而言之,如果你导入一个小的JavaScript文件:

<script type='text/javascript' src="//wurfl.io/wurfl.js"></script>

您将得到一个类似于以下JSON对象:

{
 "complete_device_name":"Google Nexus 7",
 "is_mobile":true,
 "form_factor":"Tablet"
}

(假设您使用的是Nexus 7)您将能够执行以下操作:
if(WURFL.is_mobile) {
    //dostuff();
}

这就是您正在寻找的内容。
免责声明:我在这个提供免费服务的公司工作。

Nexus 7似乎有些问题。你确定你没有在设置中欺骗UA字符串吗?至于iPad mini,是的,很难与其他iPad区分,但它仍然被识别为iPad,对吧? 是你给我的帖子投了反对票吗? - Luca P.
不,iPad mini被识别为桌面设备。 - Jacob

9

我知道这是关于这种检测的一个非常老的问题。

我的解决方案基于滚动条的宽度(是否存在)。

// this function will check the width of scroller
// if scroller width is 0px it's mobile device

//function ismob() {
    var dv = document.getElementById('divscr');
    var sp=document.getElementById('res');
    if (dv.offsetWidth - dv.clientWidth == 10) {sp.innerHTML='Is mobile'; //return true; 
    } else {
    sp.innerHTML='It is not mobile'; //return false;
    }
//}
<!-- put hidden div on very begining of page -->
<div id="divscr" style="position:fixed;top:0;left:0;width:50px;height:50px;overflow:hidden;overflow-y:scroll;z-index:-1;visibility:hidden;"></div>
<span id="res"></span>


我喜欢这个解决方案,有没有任何理由我们不应该使用它? - James
3
太棒了!并且完全支持跨浏览器。谢谢!编辑:最好检查 (dv.offsetWidth - dv.clientWidth) == 0,因为如果窗口缩放,在大多数现代高分辨率但屏幕较小的笔记本电脑(例如15.6英寸屏幕上的4k分辨率)中,滚动条会变得小于10像素。 - Ivan
多么独特的解决方案啊。我还没有在其他地方看到过这样的东西。我可以想象这可能会遇到问题,例如当滚动条被隐藏时(例如 ::-webkit-scrollbar { display: none })。有人测试过吗? - oldboy
@oldboy 尝试为 div (id="divscr") 设置可见的滚动条。我不使用 Chrome,也不想仅仅为了测试目的而安装它。有人能帮忙吗? - nelek
很棒的解决方案! 我刚刚删除了现有div的需求:function is_mobile() { var div = document.createElement('div'); div.style.position = 'fixed'; div.style.left = 0; div.style.top = 0; div.style.width = '50px'; div.style.height = '50px'; div.style.overflowY = 'scroll'; document.body.append(div); if (div.offsetWidth - div.clientWidth == 0) { var ret = true; } else { var ret = false; } div.remove(); return ret; } - Spider IT
你在这里测试叠加滚动条,没有其他的内容。它们也适用于桌面版Safari浏览器,但如果将鼠标连接到该设备上,则会更改。因此,不是桌面电脑的好标志... - HolgerJeromin

8
您可以使用媒体查询来轻松处理它。
isMobile = function(){
    var isMobile = window.matchMedia("only screen and (max-width: 760px)");
    return isMobile.matches ? true : false
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接