急!华为手机-鸿蒙系统兼容性问题,快检查你的项目

143 阅读5分钟

一、背景:pdf预览

我司预览pdf时,pc端使用的是微软的在线预览,样式如下:

image.png

或者使用pdfjs预览:

image.png

这些预览插件在pc端表现不错,但是在移动端表现不尽如人意,尤其是在遇到不同的型号的浏览器时,兼容性问题层出不穷

为了统一解决pdf在h5端的预览,我找了个插件:pdfh5,它可以很轻松的预览pdf,不挑机型,都显示这样

image.png

二、判断设备类型

由于pc和h5使用的插件不一样,那么肯定要判断设备类型,众所周知,navigator.userAgent就是专门用来判断设备的,它可以识别出pc还是h5,识别出浏览器类型

谷歌:

image.png 火狐:

image.png QQ浏览器:

image.png

我的vivo手机自带浏览器(可以看到Android、Mobile、VivoBrowser等关键信息):

image.png

于是我们可以封装一个函数,用来判断设备:

function getDeviceType(userAgent) {
  userAgent = userAgent || navigator.userAgent
  // 检查是否为移动设备
  const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)
  // 检查是否为平板设备
  const isTablet =
    /Tablet|iPad|PlayBook|Nexus 7|Nexus 10|Kindle|Silk|GT-P1000|GT-P1010|GT-P7500|GT-P7510|SCH-I800M|SHW-M180S|SM-T320|SM-T350|SM-T520|SM-T550|SM-T560|SM-T800|SM-T805|SM-T807|SM-T820|SM-T830|SM-T850|SM-T900|SM-T905|SM-T920|SM-T950|SM-T960|SM-T970|SM-T975|SM-T980|SM-T985|SM-T990|SM-T995|SM-T999|SM-T810|SM-T815|SM-T817|SM-T825|SM-T835|SM-T855|SM-T860|SM-T870|SM-T880|SM-T890|SM-T895|SM-T900|SM-T905|SM-T920|SM-T950|SM-T960|SM-T970|SM-T975|SM-T980|SM-T985|SM-T990|SM-T995|SM-T999/i.test(
      userAgent
    )
  // 如果是移动设备但不是平板设备,则为手机
  if ((isMobile || isHarmonyPhone) && !isTablet) {
    return "Mobile"
  } else if (isTablet) {
    return "Tablet"
  } else {
    return "PC"
  }
}

三、问题点

  1. 以上判断设置机型的方法,在绝大多数情况下,都是适用的;或者说在鸿蒙系统之前,在h5端都没问题

image.png

但是在华为的鸿蒙系统出来后,判断设备时,它有自己的一些特殊标识,需要将鸿蒙系统考虑进去

  1. 此外,在老版的鸿蒙系统中,自带的浏览器打印出来的userAgent竟然和pc端一样

image.png

询问AI,这是什么骚操作

image.png

所以我们封装的方法在这个浏览器上无法区分出来是pc还是h5,好在最新版的鸿蒙已不存在此问题,只需要在识别设备时将鸿蒙考虑进去即可

最终的方法(参考):

function getDeviceType(userAgent) {
  userAgent = userAgent || navigator.userAgent
  // 检查是否为移动设备
  const isMobile =
    /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
      userAgent
    )
  // 检查是否为鸿蒙手机端
  const isHarmonyPhone = /Harmony/i.test(navigator.userAgent) && /Mobile|Phone/i.test(navigator.userAgent)
  // 检查是否为平板设备
  const isTablet =
    /Tablet|iPad|PlayBook|Nexus 7|Nexus 10|Kindle|Silk|GT-P1000|GT-P1010|GT-P7500|GT-P7510|SCH-I800M|SHW-M180S|SM-T320|SM-T350|SM-T520|SM-T550|SM-T560|SM-T800|SM-T805|SM-T807|SM-T820|SM-T830|SM-T850|SM-T900|SM-T905|SM-T920|SM-T950|SM-T960|SM-T970|SM-T975|SM-T980|SM-T985|SM-T990|SM-T995|SM-T999|SM-T810|SM-T815|SM-T817|SM-T825|SM-T835|SM-T855|SM-T860|SM-T870|SM-T880|SM-T890|SM-T895|SM-T900|SM-T905|SM-T920|SM-T950|SM-T960|SM-T970|SM-T975|SM-T980|SM-T985|SM-T990|SM-T995|SM-T999/i.test(
      userAgent
    )
  // 如果是移动设备但不是平板设备,则为手机
  if ((isMobile || isHarmonyPhone) && !isTablet) {
    return "Mobile"
  } else if (isTablet) {
    return "Tablet"
  } else {
    const isSmallScreen = 'ontouchstart' in window || navigator.maxTouchPoints >= 2 || window.screen.width <= 960
    return isSmallScreen ? "Mobile": "PC"
  }
}

如果你的项目比较早,鸿蒙系统发布后,用户使用鸿蒙设备访问,可能会有个线上bug哦,自检

四、扩展

pdfh5自带的download方法进行下载,在手机端各个浏览器表现不一致

image.png

例如:

  1. 谷歌:支持设置pdf文件名,但文件超过8M时,下载不了
  2. vivo浏览器:不支持设置pdf文件名
  3. QQ浏览器:不支持设置pdf文件名 ...

通过创建a元素实现下载,实测几个浏览器都没问题,苹果手机也支持,鸿蒙也支持

function downloadUrl(url,fileName){
  let title = fileName;
    let urlName = url.split('/'),
       urlNameLen  = urlName.length-1;

    if(!title){
      title = urlName[urlNameLen]
    }
    fetch(url)
    // 获取 blob 对象
    .then(res=>res.blob())
    .then(blob=>{
      var link = document.createElement('a');
      link.style.display = 'none';
      document.body.appendChild(link);
      var url = window.URL.createObjectURL(blob);
      link.href = url;
      link.download = title;
      link.click();
      //下载完成后清理URL对象和a标签
      window.URL.revokeObjectURL(url);
      document.body.removeChild(link);
    })

}

如果你觉得这篇文章对你有用,可以看看作者封装的库xtt-utils,里面封装了非常实用的js方法。如果你也是vue开发者,那更好了,除了常用的api,还有大量的基于element-ui组件库二次封装的使用方法和自定义指令等,帮你提升开发效率。不定期更新,欢迎交流~