2021,Hybrid移动端的年终总结

1,345 阅读4分钟

PK创意闹新春,我正在参加「春节创意投稿大赛」

1、旧版安卓手机移动端垂直居中的问题

开发的时候发现一个垂直居中的效果在ios上是好的,安卓上会整体靠上些,大概搜了一下现有解释,会由以下方法导致

  • 字体大于12px是没有问题的
  • 字体小于12px 安卓上会整体靠上些
    font-size 小于 12px 的时候,利用 line-height 属性进行垂直居中布局明显是偏上的,这里为了避免由于 font-size 是奇数带来的偏差,特意把 font-size 都设置成了偶数

解决方案:
1、font-szie放大一倍,在用transform 的 scale缩小;
2、table布局

.container {
    display: table;
}
.tips {
    background-color: gray;
    font-size: 10px;
    display: table-cell;
    vertical-align: middle;
}

2、低端系统的安卓手机移动端中文字体设置加粗font-weight:600;无效

设置数值是无效的,需要设置成font-weight: bold;

3、iframe在ios上不能滚动

主要解决方案是在iframe外层添加一个div,然后设置-webkit-overflow-scrolling属性。

.webview {
  width: 100vw;
  height: 100vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  .webview-iframe{
    height: 100%;
    width: 100%;
  }
}

4、解决video标签在有些ios webview上无法播放的问题

把video上的src路径使用source标签引用

  <video
          loop
          autoPlay
          preload="auto"
          playsInline
          poster={vImg}
          x5-video-player-type="h5-page"
          className="palace-video"
        >
          <source src={vUrl} type="video/mp4" />
        </video>

5、在移动端Android Chrome,盒子内加overflow-y:auto后 字体会变大

页面缩小到一定的宽度,Android 上的谷歌浏览器就会决定调整文本大小并使其变大。 原因是Android Chrome 仅对具有动态高度的元素进行字体提升,只要您指定高度或最大高度,就不会应用字体提升。

解决方案:
1、

body *{
    max-height:9999999999px;
}

2、设置

<meta name="viewport" content="width=device-width, initial-scale=1">

3、

body{
    -webkit-text-size-adjust: none;
    -moz-text-size-adjust: none;
    -ms-text-size-adjust: none;
}

6、使用gulp-webp把图片转换成webp格式,在一些liunx系统上会报错

image.png

原因是gulp-webp依赖cwebp的库,有些liunx缺失对应的环境,需要安装依赖

image.png

sudo apt-get install libjpeg-dev libpng-dev libtiff-dev libgif-dev

7、在项目中尝试使用了vite,启动速度是特别快,但打包是真的有坑

打包后的文件是不会转换成es5语法的
打包后端js: image.png 使用@vitejs/plugin-legacy库可以生成2套代码,浏览器不支持使用原生 ESM 会加载兼容性的代码,但兼容性还是不够好,在一些低端安卓机不支持。

import {defineConfig} from 'vite'
const {resolve} = require('path')
import legacy from '@vitejs/plugin-legacy'
import {viteMockServe} from 'vite-plugin-mock';


export default defineConfig({
  build: {
    target:['es2015'],
  },
  plugins: [
    legacy({
      targets: ['ie >= 11'],
      additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
      polyfills: ['es.promise.finally', 'es/map', 'es/set'],
      modernPolyfills: ['es.promise.finally']
    }),
  ],
})

最后的解决方案还是得使用webpack进行打包。

8、<input/>input事件在ios上用原生键盘打中文会截断非直接输入

一个输入框,不允许输入特殊字符,标点。
通常我们会监听 input 事件:

inputElement.addEventListener('input', function(event) {
  let regex = /[^1-9a-zA-Z]/g;
  event.target.value = event.target.value.replace(regex, '');
  event.returnValue = false
});

在 Android 上是没有问题的,但是在 iOS 中,输入汉字的时候,中间过程中会输入拼音,每次输入一个字母都会触发 input 事件,你打2个字,但实际触发了十几次的 input 事件。

image.png

解决方案:compositionstartcompositionend
compositionstart 事件在用户开始进行非直接输入的时候触发,而在非直接输入结束,也即用户点选候选词或者点击「选定」按钮之后,会触发 compositionend 事件

var inputLock = false;
function do(inputElement) {
    var regex = /[^1-9a-zA-Z]/g;
    inputElement.value = inputElement.value.replace(regex, '');
}

inputElement.addEventListener('compositionstart', function() {
  inputLock = true;
});


inputElement.addEventListener('compositionend', function(event) {
  inputLock = false;
  do(event.target);
})


inputElement.addEventListener('input', function(event) {
  if (!inputLock) {
    do(event.target);
    event.returnValue = false;
  }
});

添加一个 inputLock 变量,当用户未完成直接输入前,inputLocktrue,不触发 input 事件中的逻辑,当用户完成有效输入之后,inputLock 设置为 false,触发 input 事件的逻辑。

9、Object.assign 方法不是全浏览器支持,尤其andriod和微信浏览器

需要添加对应的polyfill

10、滑动穿透

老生常谈的问题,移动端浏览器里出现dialog时,若在屏幕上滑动能触发弹窗底下的内容跟着滚动,这个是众所周知的事情。

解决方案:

打开弹窗时:

body.static {
  position: fixed;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
const scrollTop = document.scrollingElement.scrollTop;
document.body.classList.add('static');
document.body.style.top = `-${scrollTop}px`;

关闭弹窗:

const top = document.body.style.top;
document.body.classList.remove('static');
window.scrollTo(0, -parseInt(top));
document.body.style.top = '';

打开弹窗时,给body设置fixed,同时记录下当前的滚动位置,页面就不会滚动会顶部。 关闭弹窗,取消fixed定位,并把滚动条设置到当前的滚动位置。

最后

2021已过去,2022还需踩更多的坑。