移动端适配

1px边框的问题

伪类 + transform:基于media查询判断不同的设备像素比对线条进行缩放
.border_1px:before{
          content: '';
          position: absolute;
          top: 0;
          height: 1px;
          width: 100%;
          background-color: #000;
          transform-origin: 50% 0%;
        }
        @media only screen and (-webkit-min-device-pixel-ratio:2){
            .border_1px:before{
                transform: scaleY(0.5);
            }
        }
        @media only screen and (-webkit-min-device-pixel-ratio:3){
            .border_1px:before{
                transform: scaleY(0.33);
            }
        }

关于横屏

js识别
window.addEventListener("resize", ()=>{
    if (window.orientation === 180 || window.orientation === 0) { 
      // 正常方向或屏幕旋转180度
        console.log('竖屏');
    };
    if (window.orientation === 90 || window.orientation === -90 ){ 
       // 屏幕顺时钟旋转90度或屏幕逆时针旋转90度
        console.log('横屏');
    }  
});
css识别
@media screen and (orientation: portrait) {
  /*竖屏...*/
} 
@media screen and (orientation: landscape) {
  /*横屏...*/
}

图片模糊问题

media查询:只适用于背景图,使用media查询判断不同的设备像素比来显示不同精度的图片
.avatar{
            background-image: url(conardLi_1x.png);
        }
        @media only screen and (-webkit-min-device-pixel-ratio:2){
            .avatar{
                background-image: url(conardLi_2x.png);
            }
        }
        @media only screen and (-webkit-min-device-pixel-ratio:3){
            .avatar{
                background-image: url(conardLi_3x.png);
            }
        }

使用image-set:只适用于背景图
.avatar {
    background-image: -webkit-image-set( "conardLi_1x.png" 1x, "conardLi_2x.png" 2x );
}

srcset:使用img标签的srcset属性,浏览器会自动根据像素密度匹配最佳显示图片:
<img src="conardLi_1x.png" srcset=" conardLi_2x.png 2x, conardLi_3x.png 3x">

JavaScript拼接图片url:使用window.devicePixelRatio获取设备像素比,遍历所有图片,替换图片地址:
const dpr = window.devicePixelRatio;
const images =  document.querySelectorAll('img');
images.forEach((img)=>{
  img.src.replace(".", `@${dpr}x.`);
})

使用svg:SVG的全称是可缩放矢量图,不同于位图的基于像素,SVG 则是属于对图像的形状描述,所以它本质上是文本文件,体积较小,且不管放大多少倍都不会失真。除了我们手动在代码中绘制svg,我们还可以像使用位图一样使用svg图片:
<img src="conardLi.svg">
<img src="data:image/svg+xml;base64,[data]">
.avatar {
  background: url(conardLi.svg);
}

ios滑动不流畅

1.在滚动容器上增加滚动 touch 方法:将-webkit-overflow-scrolling 值设置为 touch
.wrapper {
    -webkit-overflow-scrolling: touch;
}
设置滚动条隐藏: .container ::-webkit-scrollbar {display: none;}
可能会导致使用position:fixed; 固定定位的元素,随着页面一起滚动

2.设置 overflow:设置外部 overflow 为 hidden,设置内容元素 overflow 为 auto。内部元素超出 body 即产生滚动,超出的部分 body 隐藏。
body {
    overflow-y: hidden;
}
.wrapper {
    overflow-y: auto;
}
两者结合使用更佳

iOS 上拉边界下拉出现白色空白

1. 监听事件禁止滑动:移动端触摸事件有三个,分别定义为
1. touchstart :手指放在一个DOM元素上。
2. touchmove :手指拖曳一个DOM元素。
3. touchend :手指从一个DOM元素上移开。
显然我们需要控制的是 touchmove 事件
touchmove 事件的速度是可以实现定义的,取决于硬件性能和其他实现细节
preventDefault 方法,阻止同一触点上所有默认行为,比如滚动。
由此我们找到解决方案,通过监听 touchmove,让需要滑动的地方滑动,不需要滑动的地方禁止滑动。
实现如下:
document.body.addEventListener('touchmove', function(e) {
    if(e._isScroller) return;
    // 阻止默认事件
    e.preventDefault();
}, {
    passive: false
});

页面放大或缩小不确定性行为

HTML meta 元标签标准中有个 中 viewport 属性,用来控制页面的缩放,一般用于移动端。
因此我们可以设置 maximum-scale、minimum-scale 与 user-scalable=no 用来避免这个问题
<meta name=viewport content="width=device-width, initial-scale=1.0, minimum-scale=1.0 maximum-scale=1.0, user-scalable=no">
阻止页面放大(meta不起作用时)
  window.addEventListener(
    "touchmove",
    function (event) {
      if (event.scale !== 1) {
        event.preventDefault();
      }
    },
    { passive: false }
  );

click 点击事件延时与穿透

使用 touchstart 替换 click
在原生中使用
el.addEventListener("touchstart", () => { console.log("ok"); }, false);
在 vue 中使用
<button @touchstart="handleTouchstart()">点击</button>

软键盘将页面顶起来、收起未回落问题

方案1:监听input失焦事件,失焦即回落
/iphone|ipod|ipad/i.test(navigator.appVersion) && document.addEventListener(
    "blur", (event) => {
      // 当页面没出现滚动条时才执行,因为有滚动条时,不会出现这问题
      // input textarea 标签才执行,因为 a 等标签也会触发 blur 事件
      if (
        document.documentElement.offsetHeight <= document.documentElement.clientHeight &&
        ["input", "textarea"].includes(event.target.localName)
      ) {
        document.body.scrollIntoView(); // 回顶部
      }
    },
    true
  );
方案2:软键盘将页面顶起来的解决方案,主要是通过监听页面高度变化,强制恢复成弹出前的高度。
//这里应该改成style,height属性 // 记录原有的视口高度
const originalHeight = document.body.clientHeight || document.documentElement.clientHeight;
window.onresize = function(){
  var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
  if(resizeHeight < originalHeight ){
    // 恢复内容区域高度
    // const container = document.getElementById("container")
    // 例如 container.style.height = originalHeight;
  }
}
键盘不能回落问题出现在 iOS 12+ 和 wechat 6.7.4+ 中,而在微信 H5 开发中是比较常见的 Bug。
兼容原理,1.判断版本类型 2.更改滚动的可视区域
const isWechat = window.navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i);
if (!isWechat) return;
const wechatVersion = wechatInfo[1];
const version = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
 // 如果设备类型为iOS 12+ 和wechat 6.7.4+,恢复成原来的视口
if (+wechatVersion.replace(/\./g, '') >= 674 && +version[1] >= 12) {
  window.scrollTo(0, Math.max(document.body.clientHeight, document.documentElement.clientHeight));
}
window.scrollTo(x-coord, y-coord),其中window.scrollTo(0, clientHeight)恢复成原来的视口

页面高度设定为100vh 高度出现的问题

3.在vue项目里使用
<style lang="scss" scoped>
.container {
  height: 100vh; /* 在之前设置为100vh,可以兼容某些不支持自定义属性的浏览器。*/
  height: calc(var(--vh, 1vh) * 100 - 46px);
</style>
  mounted() {
    let vh = window.innerHeight * 0.01
    document.documentElement.style.setProperty('--vh', `${vh}px`)
    window.addEventListener('resize', () => {
      let vh = window.innerHeight * 0.01
      document.documentElement.style.setProperty('--vh', `${vh}px`)
    })
  },
完美解决办法:
<template>
  <div class="module">
    <div class="module__item">20%</div>
    <div class="module__item">40%</div>
    <div class="module__item">60%</div>
    <div class="module__item">80%</div>
    <div class="module__item">100%</div>
  </div>
</template>
<script>
export default {
  mounted() {
    const vh = window.innerHeight * 0.01
    document.documentElement.style.setProperty('--vh', `${vh}px`)
     window.addEventListener('resize', () => {
      const vh = window.innerHeight * 0.01
      document.documentElement.style.setProperty('--vh', `${vh}px`)
    })
  }
}
</script>
<style>
body {
  background-color: #333;
}
.module {
  height: 100vh; /* Use vh as a fallback for browsers that do not support Custom Properties */
  height: calc(var(--vh, 1vh) * 100);
  margin: 0 auto;
  max-width: 30%;
}
.module__item {
  align-items: center;
  display: flex;
  height: 20%;
  justify-content: center;
}
.module__item:nth-child(odd) {
  background-color: #fff;
  color: #f73859;
}
.module__item:nth-child(even) {
  background-color: #f73859;
  color: #f1d08a;
}
</style>
posted @ 2020-11-05 16:00  JaneLifeVlog  阅读(73)  评论(0)    收藏  举报