移动端问题解决

2020/02/04 CSS 共 4157 字,约 12 分钟

最近一直在写移动端,以前的复制粘贴,现在的手写

等以后写多了,我想有经验了,应该也是复制粘贴吧,很多东西不到手机上,不进行手机兼容性测试,发现不了问题。记录兼容性,手机端问题

如何判断是手机端还是PC端?

  1. 通过屏幕宽度,判断是否为手机 => window.matchMedia()
const mql = window.matchMedia('(max-width: 640px)');
let isMobile = mql.matches;;
mql.onchange = () => {
  isMobile = mql.matches;
}
  1. navigator.userAgent:通过解析请求头中的User-Agent字段来判断访问设备的类型

  2. 侦测屏幕方向,手机屏幕可以随时改变方向(横屏或竖屏),桌面设备做不到。

  3. 检测手机独有的特性,但是PC没有,比如手机浏览器的 DOM 元素可以通过ontouchstart属性,为touch事件指定监听函数。桌面设备没有这个属性。(做浏览器兼容的时候 @supports

H5 与手机是如何通信的

JavaScript Bridge

URL Scheme

postMessage方法

Web Storage

移动端适配怎么做?

flex 或者grid布局

单位使用rem配合媒体查询,rem是根据html根字体大小来计算的,下面是设置根字体大小的方式

html {
  font-size: 16px;
  font-size: clamp(16px, calc(16px + 2 * (100vw - 375px) / 39), 22px);
}

@media screen and (max-width: 320px) {
  html {
    font-size: 14px;
  }
}

@supports not (width: clamp(1px, 2px, 3px)) {
  @media screen and (min-width: 375px) {
    html {
      font-size: calc(16px + 2 * (100vw - 375px) / 39);
    }
  }

  @media screen and (min-width: 414px) {
    html {
      font-size: calc(18px + 4 * (100vw - 414px) / 586);
    }
  }

  @media screen and (min-width: 1000px) {
    html {
      font-size: 22px;
    }
  }
}

http-equiv=mobile-agent

使用场景:用户使用手机,通过百度网址搜索访问站点时,如果是搜出的站点是PC站点,就自动跳转到对应的移动端站点

<meta http-equiv=”mobile-agent” content=”format=html5; url=http://xx.com/”> 表示当前访客是移动访客且支持HTML5时,转向网址 http://xx.com

生效情况:

标注Meta声明这一适配方案仅限适用于百度移动搜索,即只有当用户通过百度移动搜索访问站点时,适配才会生效;通过其他渠道则不生效。

额外知识点:

refresh(自动刷新并指向某页面),网页将在设定的时间内自动刷新并调向设定的网址。 <meta http-equiv="refresh" content="2;URL=http://xxx">

Set-Cookie(cookie设定),如果网页过期,那么网页存在本地的cookies也会被删除。 <meta http-equiv="Set-Cookie" content="name, date">

expires(网页到期时间),用于设定网页的到期时间,过期后网页必须到服务器上重新传输。 <meta http-equiv="expires" content="Sunday 26 October 2016 01:00 GMT" />

可用于将PC版页面指向移动版页面,将移动版页面指向PC版页面,这样有利于搜索引擎,对不同设备的用户提供不同类型的页面

<link rel="canonical" href="https://x.com">: 移动版页面指向PC版页面

<link rel="alternate" media="only screen and (max-width:640px)" href="https://x.com">: PC版页面指向移动版页面

如果rel的属性值是alternate,用户是手持设备并且设置设置了 media 属性,就用户可选择替换的样式

IOS 兼容系列问题

  1. IOS 滚动不顺畅,卡顿,安卓手机没有任何问题

-webkit-overflow-scrolling: touch;; MDN 的解释 -webkit-overflow-scrolling 属性控制元素在移动设备上是否使用滚动回弹效果. touch 使用具有回弹效果的滚动, 当手指从触摸屏上移开,内容会继续保持一段时间的滚动效果。继续滚动的速度和持续的时间和滚动手势的强烈程度成正比。同时也会创建一个新的堆栈上下文。

  1. 调用 focus() 进行聚焦,弹起手机原生软键盘,同一段代码在安卓里面没问题,IOS 始终键盘没有唤起 ?

<input autofocus v-model="value" ref='inputRef' @click.stop='showPopUp' /> 加上 autofocus 页面加载的时候获取焦点

移动端需求

点击页面的电话号码,调起手机里面拨号版,并且把电话号码复制到拨号板javascript 原生的方法就可以实现,而且很简单,利用 a 标签的 href 属性

    <!-- 控制它的显隐,弹框确定后,可点击,就跳到打电话页面了 :href="'tel:'+tel" 必须这样写 -->
    <a  :href="'tel:'+tel"></a>

注意了:如果 href 是一个变量值,必须那样写,常量的话就 <a href="tel:12306"></a>

在移动端页面有 input 或者 textarea 标签的时候,会调起键盘,这个是没有问题的。但是在手离开这些标签之后,键盘依旧没有收起,这是一个问题,影响了用户的体验。 后来发现在页面创建的时候就监听 touchend 事件可以避免这个。当手指从屏幕上离开的时候触发失焦事件,请测有用

document.addEventListener('touchend', e => {
  if (['INPUT', 'TEXTAREA'].indexOf(e.target.nodeName) < 0) {
    let inputArr = document.getElementsByTagName('input')
    let textareaArr = document.getElementsByTagName('textarea')
    if (inputArr.length) {
      for (let i = 0; i < inputArr.length; i++) {
        inputArr[i].blur()
      }
    }
    if (textareaArr.length) {
      for (let j = 0; j < textareaArr.length; j++) {
        textareaArr[j].blur()
      }
    }
  }
}, false)

在移动端项目用到了单击click事件的时候scrollTo滚动一定的距离。大部分的情况下是没有问题,但是对于某些安卓机型,scrollTo 会失效。这就头疼了,解决方案 scrollLeft

Window.scrollTo()

开发移动端web页面click事件失效问题

安卓浏览器不支持JS中的scrollto()等滑动方法

清除 ios 上输入框默认有内部阴影: -webkit-appearance: none

android 系统中元素被点击时产生边框: -webkit-tap-hightlight-color:rgba(0,0,0,0);-webit-user-modify:read-write-plaintext-only;

图片较大、加载较慢(尤其是背景图片)的时候,屏幕会是短暂的白色,视觉体验不好。可以给图片所在的 div 加一个与图片主色相近的背景色或者渐变背景色。这样页面加载时会先显示设置的背景色,图片加载之后则会覆盖背景色,视觉体验较好 background: #739bf9 url('') no-repeat center;

rem px em

rem官方定义『The font size of the root element』,即根元素的字体大小。rem是一个相对的CSS单位,1rem等于html元素上font-size的大小。所以,我们只要设置html上font-size的大小,就可以改变1rem所代表的大小

px 相对于显示器屏幕分辨率,无法用浏览器字体放大功能

em 的计算值等于当前元素所在的font-size计算值,比如浏览器的默认字体是16px,font-size:2em,那么内联元素的height就是32px

在移动端的开发过程中,我们有时候会使用一个插件,自动计算 px 单位转化为 rem 单位的插件。postcss-px-to-viewport 这个插件有一个不好的地方就是直接写在 dom 上面的元素的px不会进行转化,所以我们不会动态在 dom 上面写 px单位,但是如果借用第三方插件的时候,就不受我们控制了。这个要注意了

还有一种情况,有时候我们并不希望我们的px 单位转化为 rem 这个时候怎么办呢?

  @media screen and (min-width: 500px) {
    .progress-content {
      font-size: 14px;
      .progress-number {
        font-size: 24px;
      }
    }
  }

用 @media screen and 包裹的 class 的不会进行px单位的转化

安卓 5.1 版本 问题

在安卓低版本,有可能会出现网页运行不了,出现白屏的情况。追究原因是第三方包没有被转义成es5,而我们平时打包的时候也只会转化我们自己的代。这个时候就需要修改 @babel/preset-env 的配置文件 "useBuiltIns": "entry" 还有就是 vue 的配置支持 transpileDependencies 编译某些 node_modules 文件。

[译]Babel文档之@babel/preset-env


在技术的历史长河中,虽然我们素未谋面,却已相识已久,很微妙也很知足。互联网让世界变得更小,你我之间更近。

在逝去的青葱岁月中,虽然我们未曾相遇,却共同经历着一样的情愫。谁的青春不曾迷茫或焦虑亦是无奈,谁不曾年少过

在未来的日子里,让我们共享好的文章,共同学习进步。有不错的文章记得分享给我,我不会写好的文章,所以我只能做一个搬运工

我叫 sunseekers(张敏) ,千千万万个张敏与你同在,18年电子商务专业毕业,毕业后在前端搬砖

如果喜欢我的话,恰巧我也喜欢你的话,让我们手拉手,肩并肩共同前行,相互学习,互相鼓励

文档信息

Search

    Table of Contents