前端常见面试题(九)@郝晨光


请详解移动端点透,为什么会发生点透?描述发生的场景及解决方案

提到移动端点透问题,就不得不先提到移动端的click事件300ms延迟问题

一、移动端click事件300ms延迟问题

在移动端执行click事件时,通常移动端的浏览器会延迟300ms来触发对应的事件,这个问题的原因是:为了判断用户是否是双击,因为在移动端浏览器刚开始的时候,为了提升用户体验感,开发了双击缩放和双击滚动等默认行为,在之前的web开发中,体验并不明显,在当前运行速度和用户体验至上的时代,这个问题表现的特别严重。

移动端click事件300ms延迟解决方案
  1. 添加meta标签,阻止用户双击缩放,并限制视口宽度
    <meta
       name="viewport" 
       content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"
     />
    
  2. 设置CSStouch-action
    CSS属性 touch-action 用于指定某个给定的区域是否允许用户操作,以及如何响应用户操作(比如浏览器自带的划动、缩放等)。
    * {
      touch-action: none;
    }
    
  3. fastclick.js
    fastclick.js- github网址
    移动端事件触发顺序:在移动端,手指点击一个元素,会经过:touchstart => touchmove => touchend => click
    fastclick.js的原理是:FastClick的实现原理是在检测到touchend事件的时候,会通过DOM自定义事件立即触发模拟一个click事件,并把浏览器在300ms之后真正的click事件阻止掉。
    在原生js中可以如下使用
    if ('addEventListener' in document) {
    	document.addEventListener('DOMContentLoaded', function() {
    		FastClick.attach(document.body);
    	}, false);
    }
    // 文章由 郝晨光 整理,未经同意禁止转载
    
    在jquery或zpeto中可以如下使用
    $(function() {
    	FastClick.attach(document.body);
    });
    
    在cli工具中(require或者import)
    const FastClick = require('fastclick');
    // import FastClick = require('fastclick');
    FastClick.attach(document.body, options);
    
二、移动端点透问题
点透问题出现的场景

当A/B两个层上下z轴重叠,上层的A点击后消失或移开(这一点很重要),并且B元素本身有默认click事件(如a标签)或绑定了click事件。在这种情况下,点击A/B重叠的部分,就会出现点透的现象。

总结如下:

  1. A/B两个层上下z轴重叠(上下重叠,A盖着B)。
  2. 上层的A点击后消失或移开。(这一点很重要)
  3. B元素本身有默认click事件(如a标签) 或 B绑定了click事件。
点透问题的出现原因

点透问题出现的原因就是因为我们上边说过的移动端click事件300ms延迟问题,当点击上层元素时,先触发touchstart事件,然后在300ms后会触发click事件,而此时上层元素已经消失,所以下边的元素会触发click事件,这就是点透

点透问题的解决方案
  1. fastclick.js
    fastclick.js既然可以解决click300ms延迟,那必然可以解决点透问题,使用方法如上文所述。

  2. 对于B元素本身存在默认click事件的情况,使用touchend代替touchstart事件并阻止掉时A元素touchend的默认行为preventDefault(),因为触发touchend需要200ms,从而阻止click事件的产生。

  3. 使用一个(透明)遮罩层,屏蔽所有事件,然后400ms(对于IOS来说是个理想值)后自动隐藏

  4. 延迟一定的时间(300ms+)来处理事件

  5. 直接使用click事件,不考虑延迟问题

  6. 下层避开click事件,如a链接改为span等标签,使用js跳转页面



移动端为什么会有一像素问题?如何解决?

为什么会有一像素问题?

因为在移动端,由于屏幕分辨率的不同,现在分为一倍屏、二倍屏、三倍屏。在不同的分辨率上,有可能一像素被渲然成二个像素点或者三个像素点,所以在实际写代码的时候,我们写的 border: 1px solid #000; 可能实际被渲然为 2px/3px;

一像素问题的解决方案

  1. 先使用伪类元素实现边框效果,然后通过媒体查询来操控transform: scale来适配不同分辨率
    .border-bottom{
        position: relative;
    }
    .border-bottom::after {
        content: " ";
        position: absolute;
        left: 0;
        bottom: 0;
        width: 100%;
        height: 1px;
        background-color: #e4e4e4;
        -webkit-transform-origin: left bottom;
        transform-origin: left bottom;
    }
    
    /* 2倍屏 */
    @media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
        .border-bottom::after {
            -webkit-transform: scaleY(0.5);
            transform: scaleY(0.5);
        }
    }
    
    /* 3倍屏 */
    @media only screen and (-webkit-min-device-pixel-ratio: 3.0) {
        .border-bottom::after {
            -webkit-transform: scaleY(0.33);
            transform: scaleY(0.33);
        }
    }
    
  2. 使用border-image来代替border
    .border-image-1px {
        border-width: 1px 0px;
        -webkit-border-image: url("border.png") 2 0 stretch;
        border-image: url("border.png") 2 0 stretch;
    }
    
  3. 使用viewport +rem
    设置meta标签
    <meta
         name="viewport"
         id="WebViewport"
         content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    /> 
    
    并在js中通过判断当前是一倍屏还是二倍屏、三倍屏,来动态的设置meta标签的内容
    function rem() {
        document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';
        let viewport = document.querySelector("#WebViewport")
        if (window.devicePixelRatio == 1) {
            viewport.setAttribute('content', 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no')
        } 
        if (window.devicePixelRatio == 2) {
            viewport.setAttribute('content', 'width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no')
        } 
        if (window.devicePixelRatio == 3) {
            viewport.setAttribute('content', 'width=device-width, initial-scale=0.333333333, maximum-scale=0.333333333, minimum-scale=0.333333333, user-scalable=no')
        } 
    }
    rem()
    window.onresize = rem;
    // 文章由 郝晨光 整理,未经同意禁止转载
    
  4. border.css
    通过项目中引入border.css来解决


你还知不知道其他移动端的常见问题?

  1. html5调用安卓或者ios的拨号功能
    html5提供了自动调用拨号的标签,只要在a标签的href中添加tel:就可以了。
     <a href="tel:10086">点击拨打10086</a>
    
  2. IOS设备链接、按钮等点击产生灰色背景
    -webkit-tab-highlight-color:rgba(0,0,0,0);
    //去掉背景高亮
    
    -webkit-tab-highlight-color: red;
    //设置背景高亮的颜色
    
  3. ios设备微信浏览器或者Safari中fixed定位的部分会跟随滑动跳动
    在移动端始终使用absloute来模拟fixed绝对定位,而不使用fixed
  4. 移动端HTML5 audio autoplay失效问题
    由于自动播放网页中的音频或视频会给用户带来困扰或不必要的流量消耗,所以苹果系统和安卓系统通常都会禁止自动播放和使用JS的触发播放,必须由用户来触发才播放;解决方法思路:先通过用户touchstart触碰触发播放并暂停(让音频开始加载),后面用JS再操作就没问题了;解决代码:
    document.addEventListener('touchstart', function () {
        document.getElementsByTagName('audio')[0].play();
        document.getElementsByTagName('audio')[0].pause();
    });
    
  5. CSS动画页面闪白,动画卡顿,图片错乱的问题
    1.尽可能地使用合成属性transform和opacity来设计CSS3动画,不使用position的left和top来定位;
    2.开启硬件加速;
    -webkit-transform: translate3d(0, 0, 0);
    -moz-transform: translate3d(0, 0, 0);
    -ms-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0); //可以触发硬件加速,从而让浏览器在渲染动画时从CPU转向GPU 
    
  6. 长按页面元素被选中
    使用css属性user-select
    -webkit-user-select:none; // webkit浏览器  
    -khtml-user-select:none; // 早期浏览器 
    -moz-user-select:none; // 火狐 
    -ms-user-select:none; // IE10 
    user-select:none; 
    
  7. 顶部状态栏背景色
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    

    除非你先使用apple-mobile-web-app-capable指定全屏模式,否则这个meta标签不会起任何作用;
    如果content设置为default,则状态栏正常显示;
    如果设置为blank,则状态栏会有一个黑色的背景;
    如果设置为blank-translucent,则状态栏显示为黑色半透明;
    如果设置为default或blank,则页面显示在状态栏的下方,即状态栏占据上方部分;页面占据下方部分,二者没有遮挡对方或被遮挡;
    如果设置为blank-translucent,则页面会充满屏幕,其中页面顶部会被状态栏遮盖住(会覆盖页面20px高度,而iphone4和itouch4的Retina屏幕为40px);



本文简书地址: 前端常见面试题(九)@郝晨光

结言
感谢您的查阅,代码冗余或者有错误的地方望不吝赐教;菜鸟一枚,请多关照
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值