如何使用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个回答

7

看看这篇文章,它提供了一个非常好的代码片段,用于检测触摸设备时应该做什么,或者当调用touchstart事件时应该做什么:

$(function(){
  if(window.Touch) {
    touch_detect.auto_detected();
  } else {
    document.ontouchstart = touch_detect.surface;
  }
}); // End loaded jQuery
var touch_detect = {
  auto_detected: function(event){
    /* add everything you want to do onLoad here (eg. activating hover controls) */
    alert('this was auto detected');
    activateTouchArea();
  },
  surface: function(event){
    /* add everything you want to do ontouchstart here (eg. drag & drop) - you can fire this in both places */
    alert('this was detected by touching');
    activateTouchArea();
  }
}; // touch_detect
function activateTouchArea(){
  /* make sure our screen doesn't scroll when we move the "touchable area" */
  var element = document.getElementById('element_id');
  element.addEventListener("touchstart", touchStart, false);
}
function touchStart(event) {
  /* modularize preventing the default behavior so we can use it again */
  event.preventDefault();
}

在检测触摸支持方面,'ontouchstart' in document.documentElement 可能比 window.Touch 更好。更好的方法是使用 Modernizr.js(http://modernizr.com),因为他们花费了很多精力来尝试正确地检测触摸。如果您查看开发代码并搜索“touch”,则可以在 http://modernizr.com/downloads/modernizr.js 中看到他们的触摸检测代码。 - robocat
3
触摸检测让我陷入了麻烦,因为一些新的Windows 8笔记本在Chrome中检测为触摸屏,导致奇怪的结果。 - JWarner

6
请使用以下内容:
/**  * jQuery.browser.mobile (http://detectmobilebrowser.com/)  * jQuery.browser.mobile will be true if the browser is a mobile device  **/ (function(a){jQuery.browser.mobile=/android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))})(navigator.userAgent||navigator.vendor||window.opera);

然后使用这个:
if(jQuery.browser.mobile)
{
   console.log('You are using a mobile device!');
}
else
{
   console.log('You are not using a mobile device!');
}

6

所有答案都使用用户代理检测浏览器,但基于用户代理的设备检测并不是很好的解决方案,更好的方法是检测触摸设备等功能(在新版jQuery中,他们删除了$.browser并使用$.support代替)。

要检测移动设备,可以检查触摸事件:

function is_touch_device() {
  return 'ontouchstart' in window // works on most browsers 
      || 'onmsgesturechange' in window; // works on ie10
}

摘自如何使用JavaScript检测“触摸屏”设备的最佳方法?


5
很遗憾,这并不可靠,而且在配有触摸屏的台式电脑上依然会返回“true”。http://www.stucox.com/blog/you-cant-detect-a-touchscreen/ - JustAMartin
2
不要忘记带有触摸屏和完整浏览器体验的笔记本电脑。 :-) - Mike Kormendy
这可能不是检查设备是否为移动设备的正确方法,但根据您函数的名称,它非常适合检查触摸设备。我给你点赞;-) - Kathara

6
我建议使用以下字符串组合来检查设备类型。
根据Mozilla文档,推荐使用字符串Mobi。但是,一些旧平板电脑如果只使用Mobi则无法返回true,因此我们还应该使用Tablet字符串。
同样地,为了安全起见,也可以使用iPadiPhone字符串来检查设备类型。
大多数新设备仅使用Mobi字符串即可返回true
if (/Mobi|Tablet|iPad|iPhone/.test(navigator.userAgent)) {
    // do something
}

5
我必须加上“android”这个词才能在平板电脑上运行。我需要进行微调,但我喜欢这种方法。 - Andy

6

我知道这是一个老问题,有很多答案,但我认为这个函数简单易用,可以帮助检测所有移动设备、平板电脑和计算机浏览器,它可以完美地工作。

function Device_Type() 
{
    var Return_Device; 
    if(/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|android|iemobile|w3c|acs\-|alav|alca|amoi|audi|avan|benq|bird|blac|blaz|brew|cell|cldc|cmd\-|dang|doco|eric|hipt|inno|ipaq|java|jigs|kddi|keji|leno|lg\-c|lg\-d|lg\-g|lge\-|maui|maxo|midp|mits|mmef|mobi|mot\-|moto|mwbp|nec\-|newt|noki|palm|pana|pant|phil|play|port|prox|qwap|sage|sams|sany|sch\-|sec\-|send|seri|sgh\-|shar|sie\-|siem|smal|smar|sony|sph\-|symb|t\-mo|teli|tim\-|tosh|tsm\-|upg1|upsi|vk\-v|voda|wap\-|wapa|wapi|wapp|wapr|webc|winw|winw|xda|xda\-) /i.test(navigator.userAgent))
    {
        if(/(tablet|ipad|playbook)|(android(?!.*(mobi|opera mini)))/i.test(navigator.userAgent)) 
        {
            Return_Device = 'Tablet';
        }
        else
        {
            Return_Device = 'Mobile';
        }
    }
    else if(/(tablet|ipad|playbook)|(android(?!.*(mobi|opera mini)))/i.test(navigator.userAgent)) 
    {
        Return_Device = 'Tablet';
    }
    else
    {
        Return_Device = 'Desktop';
    }

    return Return_Device;
}

5
<script>
  function checkIsMobile(){
      if(navigator.userAgent.indexOf("Mobile") > 0){
        return true;
      }else{
        return false;
      }
   }
</script>

如果您在任何浏览器中尝试获得navigator.userAgent,那么我们将获取类似以下的浏览器信息:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36

如果您在移动设备上执行同样的操作,则会得到以下信息:

Mozilla/5.0 (Linux; Android 8.1.0; Pixel Build/OPP6.171019.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36

每个移动设备浏览器都有包含“Mobile”字符串的useragent。因此,我在我的代码中使用以上代码片段来检查当前用户代理是Web还是移动设备,并根据结果进行必要的更改。


5

以下是一段可以用于获取当前是否在移动浏览器上运行的函数。是的,这是一种浏览器嗅探技术,但有时这正是你所需要的。

function is_mobile() {
    var agents = ['android', 'webos', 'iphone', 'ipad', 'blackberry'];
    for(i in agents) {
        if(navigator.userAgent.match('/'+agents[i]+'/i')) {
            return true;
        }
    }
    return false;
}

1
这将无法检测到许多移动浏览器,特别是移动版Chrome。它还可能在以下一些浏览器上失败:Opera Mobile、Firefox mobile、Opera Mini、各种流行的中国移动浏览器等等。 - robocat
你不需要使用 for!+ 你忘记创建一个 RegExp。这里有一个更简单的: return !!navigator.userAgent.match(new RegExp(agents.join('|'),'i')) - oriadam

5

基于 http://detectmobilebrowser.com/ 的简单函数。

function isMobile() {
    var a = navigator.userAgent||navigator.vendor||window.opera;
    return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4));
}

4

一个使用了多种检测技术的ES6解决方案,位于try/catch块内。

该函数的作用是创建一个"TouchEvent",寻找对"ontouchstart"事件的支持,甚至可以查询mediaQueryList对象。

故意配置一些查询会失败并抛出新错误,因为我们在try/catch块中它可以用作回退以咨询用户代理。

我没有使用测试,在许多情况下,它可能会失败,也可能指出虚假阳性。

它不应用于任何实际验证,但在统计分析的一般范围内,数据量足够大可以“原谅”缺少精度,这仍然可能有用。

const isMobile = ((dc, wd) => {
    // get browser "User-Agent" or vendor ... see "opera" property in `window`
    let ua = wd.userAgent || wd.navigator.vendor || wd.opera;
    try {
        /**
         * Creating a touch event ... in modern browsers with touch screens or emulators (but not mobile) does not cause errors.
         * Otherwise, it will create a `DOMException` instance
         */
        dc.createEvent("TouchEvent");

        // check touchStart event
        (('ontouchstart' in wd) || ('ontouchstart' in dc.documentElement) || wd.DocumentTouch && wd.document instanceof DocumentTouch || wd.navigator.maxTouchPoints || wd.navigator.msMaxTouchPoints) ? void(0) : new Error('failed check "ontouchstart" event');

        // check `mediaQueryList` ... pass as modern browsers
        let mQ = wd.matchMedia && matchMedia("(pointer: coarse)");
        // if no have, throw error to use "User-Agent" sniffing test
        if ( !mQ || mQ.media !== "(pointer: coarse)" || !mQ.matches ) {
            throw new Error('failed test `mediaQueryList`');
        }

        // if there are no failures the possibility of the device being mobile is great (but not guaranteed)
        return true;
    } catch(ex) {
        // fall back to User-Agent sniffing
        return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(ua) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(ua.substr(0,4));
    }
})(document, window);


// to show result
let container = document.getElementById('result');

container.textContent = isMobile ? 'Yes, your device appears to be mobile' : 'No, your device does not appear to be mobile';
<p id="result"></p>


用于测试用户代理的正则表达式有些过时,在网站http://mobiledetect.com已经停止使用。

也许有更好的模式,但我不知道。


字体:


PS:

由于无法通过检查功能或使用正则表达式检查用户代理字符串来100%准确地识别,因此上述代码片段仅应视为:“这个问题的又一个例子”,以及:“不建议在生产环境中使用”。


那么,您建议使用什么进行“真正”的验证呢? - oldboy
在CSS4中,您可以使用@media (any-pointer: coarse)@media (pointer: coarse)来检测触摸设备。在JS中,您可以使用带有前置参数的matchMedia。+1. 这通常是正确的方法。 - Jake

4

你觉得 mobiledetect.net 怎么样?

其他解决方案似乎太基础了。这是一个轻量级的PHP类,它使用User-Agent字符串和特定的HTTP头来检测移动环境。你还可以通过使用任何第三方插件来获益于Mobile Detect:WordPress、Drupal、Joomla、Magento等。


因为问题要求使用jQuery? - Craicerjack
这个 PHP 脚本有多准确?它比客户端检测更准确吗? - oldboy

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