一、简介

​ 在响应式开发、性能优化或差异化功能设计等前端开发场景中,开发者需要精准的得知当前网页是在移动端访问,还是在PC端访问。从而根据不同的访问环境,动态加载资源、适配布局方案或切换交互模式。

​ 本文具体列举了6种通过JavaScript进行判断的具体方案,包含传统UA检测、新兴API,以及各自的优缺点等等。可根据具体的业务场景选择合适的方案,并在最后提供了更鲁棒的组合方案。

二、具体方案

1、navigator.userAgent(用户代理字符串)

​ 这是目前最常见的一种方案,通过JS获取 navigator.userAgent,即用户代理字符串,其中包含浏览器的相关信息,包括设备信息。

​ 结合正则表达式对该字符串进行判断,如果该字符串中包含mobiandroidiphoneHarmony等特定关键字,就可以认定当前设备为移动端设备,当前浏览器为移动端浏览器。

function detectDevice() {
  const ua = navigator.userAgent;
  const isMobile = /Android|webOS|iPhone|iPad|iPod|Harmony|BlackBerry|IEMobile|Opera Mini/i.test(ua);
  return isMobile ? 'Mobile' : 'PC';
}

console.log(detectDevice()); // 输出设备类型

优点: 实现简单,仅需单行正则匹配。

缺点: 用户可以对该字符串进行修改伪装(如:浏览器开发者工具),因此并不可靠;并且随着移动端设备的更新,需要不断更新特定关键词以适应新设备(如:新增的Harmony)。

2、window.orientation

​ 该方案是通过JS获取window.orientation,即屏幕方向来判断当前是否为移动端(值有:0、90、-90、180)。通常只有移动端设备才有该属性,PC端设备会返回undefined

function detectDevice() {
  return typeof window.orientation!=='undefined' ? 'Mobile' : 'PC';
}

console.log(detectDevice()); // 输出设备类型

优点: 代码简洁,无复杂逻辑。

缺点: 并非所有浏览器都支持,浏览器兼容性有一定问题;部分PC端设备也支持该属性(带有触摸屏的笔记本电脑等),因此判断结果并不可靠。

3、touch相关事件

​ 该方案是通过判断页面DOM是否存在touch相关事件(touchstarttouchmovetouchend等),来判断当前是否为移动端。通常只有移动端支持相关事件,PC端不支持。

function detectDevice() {
  return ('ontouchstart' in document.documentElement) ? 'Mobile' : 'PC';
}

console.log(detectDevice()); // 输出设备类型

优点: 检测逻辑与设备交互直接关联,自适应新设备。

缺点: 部分PC端设备也支持相关事件(带有触摸屏的笔记本电脑等), 可能会导致结果判断错误。

4、window.screen.width

​ 该方案是通过window.screen.width来获取当前设备的屏幕宽度,进而判断是否为移动端。需要设定一个边界值,例如将屏幕宽度小于760px的设备,认定为移动端设备,其余设备,认定为PC端设备。

function detectDevice() {
  return (window.screen&&window.screen.width<760) ? 'Mobile' : 'PC';
}

console.log(detectDevice()); // 输出设备类型

优点: 直接获取物理屏幕尺寸,准确度高。

缺点: 需要合理设置屏幕的宽度阈值;当手机横屏访问页面时,该属性会将手机的长度作为设备宽度,可能会导致结果判断错误。

5、window.matchMedia()

​ 该方案是通过window.matchMedia()结合CSS的媒体查询语句进行判断。该方法的参数为一个CSS的查询语句,返回值为一个对象。如果媒体查询语句结果成立,则对象的matches属性值为true,否则为false。因此可以通过媒体查询页面的宽度以及设备指针的准确性来判断当前设备是否为移动端。

​ 媒体查询语句(pointer:coarse)用于判断当前设备的指针是否准确,PC端的鼠标为准确,移动端的触摸为不准确。如果有的设备支持多种指针,比如同时支持鼠标和触摸,则可以通过(any-pointer:coarse)判断所有指针,只要有一个指针是不精确的,就属于符合条件。

function detectDevice() {
  // 如果页面的宽度小于760px 
  if(window.matchMedia("(max-width: 760px)").matches
     // 并且当前设备的指针是不精确的
     && window.matchMedia("(any-pointer:coarse)").matches) {
      // 则大概率为移动端设备
      return 'Mobile';
  }
  // 否则为PC端设备
  return 'PC';
}

console.log(detectDevice()); // 输出设备类型

优点: 组合检测,准确度更高。

缺点: 需要合理设置媒体查询的宽度阈值,any-pointer:coarse 属性有一定的浏览器兼容问题。

6、Navigator.userAgentData.mobile(实验属性)

​ 该方案通过Navigator.userAgentData.mobile直接获取当前是否在移动端设备上运行,属性值为true/false

function detectDevice() {
  return (Navigator.userAgentData&&Navigator.userAgentData.mobile) ? 'Mobile' : 'PC';
}

console.log(detectDevice()); // 输出设备类型

优点: 直接读取浏览器提供的设备标识,无需解析。

缺点: 该属性为实验属性,浏览器兼容性不好 。

三、组合方案

​ 通过三级渐进式检测对设备类型进行判断,结合UA初步过滤+硬件特征验证+交互能力确认,并通过动态权重调整,使判断结果尽可能的准确:

function detectDevice() {
  // 一级检测:实验性API(高精度)
  if (typeof navigator.userAgentData !== 'undefined' && navigator.userAgentData.mobile) {
    return 'Mobile';
  }

  // 二级检测:组合特征验证
  // 1、UA用户代理字符串判断
  const ua = navigator.userAgent;
  const isMobileUA = /Android|webOS|iPhone|iPad|iPod|Harmony|BlackBerry|IEMobile|Opera Mini/i.test(ua);
  // 2、touch事件判断
  const isTouch = 'ontouchstart' in document.documentElement;
  // 3、媒体查询宽度判断
  const isSmallScreen = window.matchMedia('(max-width: 760px)').matches;
  // 4、媒体查询指针精度判断
  const isCoarsePointer = window.matchMedia('(any-pointer: coarse)').matches;
  // 5、媒体查询hover判断
  const isHover = window.matchMedia('(any-hover: hover)').matches;

  // 特征权重评分(可根据实际情况调整阈值)
  let score = 0;
  if (isMobileUA) score += 0.3;  // UA权重30%
  if (isTouch) score += 0.2;      // 触控权重20%
  if (isSmallScreen) score += 0.25;// 屏幕权重25%
  if (isCoarsePointer) score += 0.15;// 指针权重15%
  if (!isHover) score += 0.1;     // 悬停权重10%

  // 三级检测:动态方向验证(防横屏误判)
  const isPortrait = window.matchMedia('(orientation: portrait)').matches;
  if (typeof window.orientation !== 'undefined') {
    score += isPortrait ? 0.1 : -0.05; // 竖屏加分,横屏减分
  }
  // 给出最终判断结果
  return score >= 0.6 ? 'Mobile' : 'PC'; // 总阈值60%
}

请关注公众号,查看更多优质资源:

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐