前端常見(jiàn)面試題(九)@郝晨光


請(qǐng)?jiān)斀庖苿?dòng)端點(diǎn)透,為什么會(huì)發(fā)生點(diǎn)透?描述發(fā)生的場(chǎng)景及解決方案

提到移動(dòng)端點(diǎn)透問(wèn)題,就不得不先提到移動(dòng)端的click事件300ms延遲問(wèn)題

一、移動(dòng)端click事件300ms延遲問(wèn)題

在移動(dòng)端執(zhí)行click事件時(shí),通常移動(dòng)端的瀏覽器會(huì)延遲300ms來(lái)觸發(fā)對(duì)應(yīng)的事件,這個(gè)問(wèn)題的原因是:為了判斷用戶是否是雙擊,因?yàn)樵谝苿?dòng)端瀏覽器剛開(kāi)始的時(shí)候,為了提升用戶體驗(yàn)感,開(kāi)發(fā)了雙擊縮放和雙擊滾動(dòng)等默認(rèn)行為,在之前的web開(kāi)發(fā)中,體驗(yàn)并不明顯,在當(dāng)前運(yùn)行速度和用戶體驗(yàn)至上的時(shí)代,這個(gè)問(wèn)題表現(xiàn)的特別嚴(yán)重。

移動(dòng)端click事件300ms延遲解決方案
  1. 添加meta標(biāo)簽,阻止用戶雙擊縮放,并限制視口寬度
    <meta
       name="viewport" 
       content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"
     />
    
  2. 設(shè)置CSStouch-action
    CSS屬性 touch-action 用于指定某個(gè)給定的區(qū)域是否允許用戶操作,以及如何響應(yīng)用戶操作(比如瀏覽器自帶的劃動(dòng)、縮放等)。
    * {
      touch-action: none;
    }
    
  3. fastclick.js
    fastclick.js- github網(wǎng)址
    移動(dòng)端事件觸發(fā)順序:在移動(dòng)端,手指點(diǎn)擊一個(gè)元素,會(huì)經(jīng)過(guò):touchstart => touchmove => touchend => click
    fastclick.js的原理是:FastClick的實(shí)現(xiàn)原理是在檢測(cè)到touchend事件的時(shí)候,會(huì)通過(guò)DOM自定義事件立即觸發(fā)模擬一個(gè)click事件,并把瀏覽器在300ms之后真正的click事件阻止掉。
    在原生js中可以如下使用
    if ('addEventListener' in document) {
        document.addEventListener('DOMContentLoaded', function() {
            FastClick.attach(document.body);
        }, false);
    }
    // 文章由 郝晨光 整理,未經(jīng)同意禁止轉(zhuǎn)載
    
    在jquery或zpeto中可以如下使用
    $(function() {
        FastClick.attach(document.body);
    });
    
    在cli工具中(require或者import)
    const FastClick = require('fastclick');
    // import FastClick from 'fastclick';
    FastClick.attach(document.body, options);
    

二、移動(dòng)端點(diǎn)透問(wèn)題

點(diǎn)透問(wèn)題出現(xiàn)的場(chǎng)景

當(dāng)A/B兩個(gè)層上下z軸重疊,上層的A點(diǎn)擊后消失或移開(kāi)(這一點(diǎn)很重要),并且B元素本身有默認(rèn)click事件(如a標(biāo)簽)或綁定了click事件。在這種情況下,點(diǎn)擊A/B重疊的部分,就會(huì)出現(xiàn)點(diǎn)透的現(xiàn)象。

總結(jié)如下:

  1. A/B兩個(gè)層上下z軸重疊(上下重疊,A蓋著B)。
  2. 上層的A點(diǎn)擊后消失或移開(kāi)。(這一點(diǎn)很重要)
  3. B元素本身有默認(rèn)click事件(如a標(biāo)簽) 或 B綁定了click事件。
點(diǎn)透問(wèn)題的出現(xiàn)原因

點(diǎn)透問(wèn)題出現(xiàn)的原因就是因?yàn)槲覀兩线呎f(shuō)過(guò)的移動(dòng)端click事件300ms延遲問(wèn)題,當(dāng)點(diǎn)擊上層元素時(shí),先觸發(fā)touchstart事件,然后在300ms后會(huì)觸發(fā)click事件,而此時(shí)上層元素已經(jīng)消失,所以下邊的元素會(huì)觸發(fā)click事件,這就是點(diǎn)透

點(diǎn)透問(wèn)題的解決方案
  1. fastclick.js
    fastclick.js既然可以解決click300ms延遲,那必然可以解決點(diǎn)透問(wèn)題,使用方法如上文所述。

  2. 對(duì)于B元素本身存在默認(rèn)click事件的情況,使用touchend代替touchstart事件并阻止掉時(shí)A元素touchend的默認(rèn)行為preventDefault(),因?yàn)橛|發(fā)touchend需要200ms,從而阻止click事件的產(chǎn)生。

  3. 使用一個(gè)(透明)遮罩層,屏蔽所有事件,然后400ms(對(duì)于IOS來(lái)說(shuō)是個(gè)理想值)后自動(dòng)隱藏

  4. 延遲一定的時(shí)間(300ms+)來(lái)處理事件

  5. 直接使用click事件,不考慮延遲問(wèn)題

  6. 下層避開(kāi)click事件,如a鏈接改為span等標(biāo)簽,使用js跳轉(zhuǎn)頁(yè)面



移動(dòng)端為什么會(huì)有一像素問(wèn)題?如何解決?

為什么會(huì)有一像素問(wèn)題?

因?yàn)樵谝苿?dòng)端,由于屏幕分辨率的不同,現(xiàn)在分為一倍屏、二倍屏、三倍屏。在不同的分辨率上,有可能一像素被渲然成二個(gè)像素點(diǎn)或者三個(gè)像素點(diǎn),所以在實(shí)際寫代碼的時(shí)候,我們寫的 border: 1px solid #000; 可能實(shí)際被渲然為 2px/3px;

一像素問(wèn)題的解決方案

  1. 先使用偽類元素實(shí)現(xiàn)邊框效果,然后通過(guò)媒體查詢來(lái)操控transform: scale來(lái)適配不同分辨率
    .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來(lái)代替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
    設(shè)置meta標(biāo)簽
    <meta
         name="viewport"
         id="WebViewport"
         content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    /> 
    
    并在js中通過(guò)判斷當(dāng)前是一倍屏還是二倍屏、三倍屏,來(lái)動(dòng)態(tài)的設(shè)置meta標(biāo)簽的內(nèi)容
    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;
    // 文章由 郝晨光 整理,未經(jīng)同意禁止轉(zhuǎn)載
    
  4. border.css
    通過(guò)項(xiàng)目中引入border.css來(lái)解決



你還知不知道其他移動(dòng)端的常見(jiàn)問(wèn)題?

  1. html5調(diào)用安卓或者ios的撥號(hào)功能
    html5提供了自動(dòng)調(diào)用撥號(hào)的標(biāo)簽,只要在a標(biāo)簽的href中添加tel:就可以了。

     <a href="tel:10086">點(diǎn)擊撥打10086</a>
    
  2. IOS設(shè)備鏈接、按鈕等點(diǎn)擊產(chǎn)生灰色背景

    -webkit-tab-highlight-color:rgba(0,0,0,0);
    //去掉背景高亮
    
    -webkit-tab-highlight-color: red;
    //設(shè)置背景高亮的顏色
    
  3. ios設(shè)備微信瀏覽器或者Safari中fixed定位的部分會(huì)跟隨滑動(dòng)跳動(dòng)
    在移動(dòng)端始終使用absloute來(lái)模擬fixed絕對(duì)定位,而不使用fixed

  4. 移動(dòng)端HTML5 audio autoplay失效問(wèn)題
    由于自動(dòng)播放網(wǎng)頁(yè)中的音頻或視頻會(huì)給用戶帶來(lái)困擾或不必要的流量消耗,所以蘋果系統(tǒng)和安卓系統(tǒng)通常都會(huì)禁止自動(dòng)播放和使用JS的觸發(fā)播放,必須由用戶來(lái)觸發(fā)才播放;解決方法思路:先通過(guò)用戶touchstart觸碰觸發(fā)播放并暫停(讓音頻開(kāi)始加載),后面用JS再操作就沒(méi)問(wèn)題了;解決代碼:

    document.addEventListener('touchstart', function () {
        document.getElementsByTagName('audio')[0].play();
        document.getElementsByTagName('audio')[0].pause();
    });
    
  5. CSS動(dòng)畫頁(yè)面閃白,動(dòng)畫卡頓,圖片錯(cuò)亂的問(wèn)題
    1.盡可能地使用合成屬性transform和opacity來(lái)設(shè)計(jì)CSS3動(dòng)畫,不使用position的left和top來(lái)定位;
    2.開(kāi)啟硬件加速;

    -webkit-transform: translate3d(0, 0, 0);
    -moz-transform: translate3d(0, 0, 0);
    -ms-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0); //可以觸發(fā)硬件加速,從而讓瀏覽器在渲染動(dòng)畫時(shí)從CPU轉(zhuǎn)向GPU 
    
  6. 長(zhǎng)按頁(yè)面元素被選中
    使用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. 頂部狀態(tài)欄背景色

    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    

    除非你先使用apple-mobile-web-app-capable指定全屏模式,否則這個(gè)meta標(biāo)簽不會(huì)起任何作用;
    如果content設(shè)置為default,則狀態(tài)欄正常顯示;
    如果設(shè)置為blank,則狀態(tài)欄會(huì)有一個(gè)黑色的背景;
    如果設(shè)置為blank-translucent,則狀態(tài)欄顯示為黑色半透明;
    如果設(shè)置為default或blank,則頁(yè)面顯示在狀態(tài)欄的下方,即狀態(tài)欄占據(jù)上方部分;頁(yè)面占據(jù)下方部分,二者沒(méi)有遮擋對(duì)方或被遮擋;
    如果設(shè)置為blank-translucent,則頁(yè)面會(huì)充滿屏幕,其中頁(yè)面頂部會(huì)被狀態(tài)欄遮蓋住(會(huì)覆蓋頁(yè)面20px高度,而iphone4和itouch4的Retina屏幕為40px);



如果本文對(duì)您有幫助,可以看看本人的其他文章:
前端常見(jiàn)面試題(八)@郝晨光
前端常見(jiàn)面試題(七)@郝晨光
前端常見(jiàn)面試題(六)@郝晨光

友情鏈接:Vue-cli3.0二次封裝axios @于志程

本文 CSDN 地址: 前端常見(jiàn)面試題(九)@郝晨光

結(jié)言
感謝您的查閱,本文由郝晨光整理并總結(jié),代碼冗余或者有錯(cuò)誤的地方望不吝賜教;菜鳥一枚,請(qǐng)多關(guān)照
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • # 移動(dòng)端開(kāi)發(fā) ### 1. 1px問(wèn)題如何解決 #### ①偽類 + transform(比較完美) > 原理是...
    sunnyRube閱讀 986評(píng)論 0 0
  • meta基礎(chǔ)知識(shí) H5頁(yè)面窗口自動(dòng)調(diào)整到設(shè)備寬度,并禁止用戶縮放頁(yè)面 忽略將頁(yè)面中的數(shù)字識(shí)別為電話號(hào)碼 忽略And...
    Mycro閱讀 619評(píng)論 0 2
  • 請(qǐng)參看我github中的wiki,不定期更新。https://github.com/ivonzhang/Front...
    zhangivon閱讀 7,743評(píng)論 2 19
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML標(biāo)準(zhǔn)。 注意:講述HT...
    kismetajun閱讀 28,774評(píng)論 1 45
  • 一日之計(jì)在于晨, 一年之計(jì)在于春… 日曰復(fù)明日,明日何其多?。 山東,青島。
    春風(fēng)化雨閱讀 221評(píng)論 0 0

友情鏈接更多精彩內(nèi)容