题 在jQuery中检测移动设备的最佳方法是什么?


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

jQuery $.browser 功能不是我要找的。


1362


起源


提供专门针对移动设备的移动网址。这是大多数主要网站处理移动设备的方式。看到 m.google.com。 - meagar♦
jQuery没有,也无法做到一切。它提供了跨浏览器的DOM遍历和操作,简单的动画和浏览器之间的ajax,并为插件构建了一个框架框架。在询问之前请注意jQuery的局限性 特别 对于jQuery解决方案。 - Yi Jiang
用户代理是不断移动的目标,阅读这篇文章的每个人都应该非常警惕用户代理嗅探 - Rob
什么是“移动”设备?它是支持触摸的设备(包括带有鼠标的Chrome Pixels和Windows 8笔记本电脑)吗?它是一个小屏幕的设备(视网膜iPad怎么样)?它是一个CPU速度慢的设备吗?或者互联网连接速度慢的设备?根据您的要求,这个问题的答案会有所不同。目标屏幕分辨率或触摸很容易。如果你想为某些设备提供更小的内容或更少密集的JS,那么就没有灵丹妙药了。测试window.navigator.connection并回退到(讨厌的,坏的,不明智的)userAgent嗅探。我的2美分。 - David Gilbertson
@Cole“Cole9”Johnson我的观点完全正确。 “移动”似乎被用作触摸,慢速CPU,慢速网络和小屏幕的总称。但这些都不是完美的假设。我认为,单独考虑这些将产生比设计一些模糊的“移动”概念更好的产品。因此,我向OP提出了这个问题。 - David Gilbertson


答案:


您可以使用简单的JavaScript来检测它,而不是使用jQuery:

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

或者你可以将它们结合起来,使它更容易通过jQuery访问...

$.browser.device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));

现在 $.browser 将返回 "device" 适用于所有上述设备

注意: $.browser 删除 jQuery v1.9.1。但您可以通过使用jQuery迁移插件来使用它


更彻底的版本:

var isMobile = false; //initiate as false
// device detection
if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|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(navigator.userAgent) 
    || /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(navigator.userAgent.substr(0,4))) { 
    isMobile = true;
}

1737



用户代理嗅探是一种非常节俭的检测技术,用户代理字符串是一个不变的移动目标,它们不应该被单独信任。投票给这篇文章的人应该考虑更多的研究。 - Rob
从用户代理中嗅探特定设备的问题之一是,您必须记住在新设备出现时更新检测。这不是一个理想的解决方案。 - ICodeForCoffee
Android上的Dolphin浏览器不会发送任何这些字符串! - feeela
如果您的用户足够狡猾,或者开发人员愚蠢到无法更改用户代理字符串,谁会关心他们...... - mattdlockyer
那么你认为用鼠标安卓手机的手机怎么样? Windows PC可以在双模式下运行(带键盘还是触摸屏)?如果您在iPad发明之前就已经这样做了,那么您必须稍后将其添加到您的所有网站。下一个操作系统问世:Ubuntu Mobile,FirefoxOS,Tizen ...... .This.Is.A.Bad.Idea. - FrancescoMM


对我来说小小是美丽的所以我正在使用这种技术:

在CSS文件中:

/* Smartphones ----------- */
@media only screen and (max-width: 760px) {
  #some-element { display: none; }
}

在jQuery / JavaScript文件中:

$( document ).ready(function() {      
    var is_mobile = false;

    if( $('#some-element').css('display')=='none') {
        is_mobile = true;       
    }

    // now i can use is_mobile to run javascript conditionally

    if (is_mobile == true) {
        //Conditional script here
    }
 });

我的目标是让我的网站“移动友好”。所以我使用CSS Media Queries根据屏幕大小显示/隐藏元素。

例如,在我的移动版本中,我不想激活Facebook Like Box,因为它会加载所有这些配置文件图像和内容。这对移动访问者来说并不好。所以,除了隐藏容器元素之外,我还在jQuery代码块(上面)中执行此操作:

if(!is_mobile) {
    (function(d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) return;
        js = d.createElement(s); js.id = id;
        js.src = "//connect.facebook.net/pt_PT/all.js#xfbml=1&appId=210731252294735";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
}

你可以在行动中看到它 http://lisboaautentica.com

我还在研究移动版本,所以它仍然没有看起来应该如此。

更新 dekin88

内置了一个用于检测媒体的JavaScript API。 而不是使用上述解决方案,只需使用以下内容:

$( document ).ready(function() {      
    var isMobile = window.matchMedia("only screen and (max-width: 760px)");

    if (isMobile.matches) {
        //Conditional script here
    }
 });

浏览器支持:  http://caniuse.com/#feat=matchmedia

这种方法的优点是它不仅更简单,而且更短,但如果需要,您可以有条件地针对不同的设备(如智能手机和平板电脑),而无需在DOM中添加任何虚拟元素。


411



你不需要在DOM中实际使用#some-element来实现这个目的吗? - Rimer
-1 screen.width 属性 是一个全球性的。没有必要随意向DOM添加元素,并且不必要地引入CSS媒体查询。另外,如果浏览器在桌面上并且用户调整窗口大小, $is_mobile 不会更新。 - merv
为什么不: if( screen.width <= 480 ) { // is mobile } - andrewrjones
@andrewrjones Retina设备翻倍 width 属性值IIRC。因此,视网膜iPhone将有一个 width 的 640 和高度 960 在肖像,和 width 的 960 和高度 640 在景观中。 - Cole Johnson
你刚刚彻底改造了 window.matchMedia: developer.mozilla.org/en-US/docs/Web/API/Window.matchMedia - Paul Irish


根据 Mozilla - 使用用户代理进行浏览器检测

总之,我们建议在用户代理中的任何位置查找字符串“Mobi”以检测移动设备。

喜欢这个:

if (/Mobi/.test(navigator.userAgent)) {
    // mobile!
}

这将匹配所有常见的移动浏览器用户代理,包括移动Mozilla,Safari,IE,Opera,Chrome等。

Android更新

EricL建议进行测试 Android 作为用户代理也是如此 Chrome用户代理字符串 对于平板电脑不包括“Mobi”(但手机版本):

if (/Mobi|Android/i.test(navigator.userAgent)) {
    // mobile!
}

178



感谢你的回答!我更喜欢 /Mobi/i.test(navigator.userAgent) 但是,作为 测试() 它返回一个布尔值。 - arminrosu
矛盾的是,三星Galaxy Note 8上的FireFox Mobile不会返回Mobi,测试将返回false。 - Eirinn
链接文章提到: 如果设备足够大而没有标记为“Mobi”,则应该为桌面站点提供服务(最佳做法是,无论如何都应该支持触摸输入,因为更多台式机出现在触摸屏上)。 - QuasarDonkey
这比其他建议的解决方案好得多,它应该是接受的答案i.m.o. - RNobel
DERP。谢谢。我无法编辑我以前的帖子。这又是:/Mobi/i.test(navigator.userAgent) || /Android/i.test(navigator.userAgent) - EricL


你想要检测一个移动设备你正在做什么是有点太接近“浏览器嗅探”概念IMO。进行一些特征检测可能要好得多。像这样的图书馆 http://www.modernizr.com/ 可以帮助你。

例如,移动和非移动之间的界限在哪里?它每天变得越来越模糊。


74



仍然,用户可能希望为这些设备使用“jquery mobile”,无论支持的功能如何。 - Sirber
例如,我的“移动”“非移动”问题是我的翻转功能,我有JS设置关闭功能,只需要检测 - Sam Sussman
不过,如果您想提供特定于设备的可下载应用程序,它可能很有用。 - Bastes
这取决于具体情况,我正在寻找能告诉我用户是否在移动设备上的东西,以便我可以禁用一些繁重的基于JavaScript的动画。 UA嗅探比尝试“检测”用户浏览器的JavaScript性能更合适。 - ricksuggs
移动与非移动是一个非常大的区别,当您尝试为移动/桌面体验提供交互/ ui时,仅使用“特征检测”是愚蠢的。就个人而言,我希望有一种简单(可靠)的方式来获取当前浏览器运行的操作系统 - nbsp


一个简单而有效的单线程:

function isMobile() { return ('ontouchstart' in document.documentElement); }

但是上面的代码没有考虑带触摸屏的笔记本电脑的情况。 因此,我提供了第二个版本,基于 @Julian解决方案

function isMobile() {
  try{ document.createEvent("TouchEvent"); return true; }
  catch(e){ return false; }
}

72



带触摸屏的Windows笔记本电脑怎么样? - Chris Cinelli
第二 isMobile 你提供的功能返回 true 在我的设备上! (谷歌Chrome v44.0) - Luke
这更像是一个isTouchSupported方法,而不是真正的移动检测。 - Martin Barker
并非所有手机都有触摸屏。 - Andrew
@LukeP从移动模拟到桌面时,您是否清爽? - Christian4423


这不是jQuery,但我发现了这个: http://detectmobilebrowser.com/

它提供了以多种语言检测移动浏览器的脚本,其中一种是JavaScript。这可能会帮助你找到你想要的东西。

但是,由于您使用的是jQuery,因此您可能希望了解jQuery.support集合。它是用于检测当前浏览器功能的一组属性。文档在这里: http://api.jquery.com/jQuery.support/

由于我不知道你想要完成什么,我不知道哪一个最有用。

所有这一切,我认为最好的办法是使用服务器端语言(如果这是一个选项)将不同的脚本重定向或写入输出。由于您并不真正了解移动浏览器x的功能,因此在服务器端执行检测和更改逻辑将是最可靠的方法。当然,如果你不能使用服务器端语言,所有这一切都没有实际意义:)


59



这不支持iPad。要支持iPad,请查找ip(hone | od)和“| ad” - 例如IP(磨练| OD |广告) - Jayson Ragasa
我刚尝试了detectmobilebrowser.com/的javascript,而且它不适用于iPad。 - Milche Patern
@MilchePatern那是因为脚本有问题,使用iPad代替ipad,然后就可以了,我的三星Tab上有问题,不得不使用Android iso android :) - Coen Damen
那里有一个jQuery版本,它可以很好地工作,但是对于平板电脑检测,你必须添加 |android|ipad|playbook|silk 如中描述的那样 关于部分 (这是设计) - cprcrack
好吧,平板电脑不是手机。该网站称为dectect 移动 浏览器。 - Felix Eve


有时需要知道客户端使用哪个品牌设备才能显示特定于该设备的内容,例如指向iPhone商店或Android市场的链接。 Modernizer很棒,但只显示浏览器功能,如HTML5或Flash。

这是我在jQuery中的UserAgent解决方案,为每种设备类型显示不同的类:

/*** sniff the UA of the client and show hidden div's for that device ***/
var customizeForDevice = function(){
    var ua = navigator.userAgent;
    var checker = {
      iphone: ua.match(/(iPhone|iPod|iPad)/),
      blackberry: ua.match(/BlackBerry/),
      android: ua.match(/Android/)
    };
    if (checker.android){
        $('.android-only').show();
    }
    else if (checker.iphone){
        $('.idevice-only').show();
    }
    else if (checker.blackberry){
        $('.berry-only').show();
    }
    else {
        $('.unknown-device').show();
    }
}

这个解决方案来自Graphics Maniacs http://graphicmaniacs.com/note/detecting-iphone-ipod-ipad-android-and-blackberry-browser-with-javascript-and-php/


45



这很好用。我需要禁用在使用iPad或Android手机时滚动运行的jQuery函数,并且由于各种设备具有不同的屏幕宽度,这是一个简单的解决方案。万分感谢。 - Eric Allen
使用Android测试的唯一问题是使用android用户代理的角落 - MayorMonty
很好的答案表明我们不必是特征检测原教旨主义者。 - Fernando


找到了解决方案: http://www.abeautifulsite.net/blog/2011/11/detecting-mobile-devices-with-javascript/

var isMobile = {
    Android: function() {
        return navigator.userAgent.match(/Android/i);
    },
    BlackBerry: function() {
        return navigator.userAgent.match(/BlackBerry/i);
    },
    iOS: function() {
        return navigator.userAgent.match(/iPhone|iPad|iPod/i);
    },
    Opera: function() {
        return navigator.userAgent.match(/Opera Mini/i);
    },
    Windows: function() {
        return navigator.userAgent.match(/IEMobile/i);
    },
    any: function() {
        return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
    }
};

然后验证它是否为Mobile,您可以使用以下方法进行测试:

if(isMobile.any()) {
   //some code...
}

39



当您可以确信子字符串直接与设备类型相关时,基于用户代理的解决方案很有效。即iPad = iPad。然而,现在有这么多不同类型的设备(超过25,000),该方法对于大多数商业目的而言不够准确。我创建了开源项目 51Degrees.com 提供可靠和强大的替代方案。它可以在JavaScript和服务器端工作。所有文件都在这里...... 51degrees.com/support/documentation - James Rosewell
我上面也用过,它对我来说效果很好,但现在它不适用于Android 5.1及以上版本,Android 5.1及更高版本有什么变化吗? - Imran Qamer


如果用“手机”你的意思是“小屏幕”,我用这个:

var windowWidth = window.screen.width < window.outerWidth ?
                  window.screen.width : window.outerWidth;
var mobile = windowWidth < 500;

在iPhone上,你最终会得到一个window.screen.width为320.在Android上,你最终会得到一个window.outerWidth为480(虽然这可能取决于Android)。 iPad和Android平板电脑将返回768这样的数字,因此它们可以像您想要的那样获得完整视图。


18



为什么'window.screen.width'不够?看起来你正在使用'window.screen.width'或'window.outerWidth'中较小的一个。你为什么关心'outerWidth'?在此先感谢您的回答! - user1330974