2021-03-04

移動的端常見問題

ios滑動不流暢

  • 上下滑動頁面會產(chǎn)生卡頓忿檩,手指離開頁面东抹,頁面立即停止運動。整體表現(xiàn)就是滑動不流暢蜒简,沒有滑動慣性瘸羡。

  • 原來在 iOS 5.0 以及之后的版本,滑動有定義有兩個值 autotouch搓茬,默認值為 auto犹赖。

    -webkit-overflow-scrolling: touch; /* 當手指從觸摸屏上移開,會保持一段時間的滾動 */
    
    -webkit-overflow-scrolling: auto; /* 當手指從觸摸屏上移開卷仑,滾動會立即停止 */
    
  • 在滾動容器上增加滾動 touch 方法

    .wrapper {
        -webkit-overflow-scrolling: touch;
    }
    
  • 設置 overflow

    設置外部 overflowhidden,設置內(nèi)容元素 overflowauto峻村。內(nèi)部元素超出 body 即產(chǎn)生滾動,超出的部分 body 隱藏锡凝。

    body {
        overflow-y: hidden;
    }
    .wrapper {
        overflow-y: auto;
    }
    

頁面放大或縮小不確定性行為

  • 雙擊或者雙指張開手指頁面元素粘昨,頁面會放大或縮小。

  • 移動端常規(guī)寫法

    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
  • 因此我們可以設置 maximum-scale窜锯、minimum-scaleuser-scalable=no 用來避免這個問題

    <meta name=viewport
      content="width=device-width, initial-scale=1.0, minimum-scale=1.0 maximum-scale=1.0, user-scalable=no">
    

click 點擊事件延時與穿透

  • 監(jiān)聽元素 click 事件张肾,點擊元素觸發(fā)時間延遲約 300ms

  • 點擊蒙層锚扎,蒙層消失后吞瞪,下層元素點擊觸發(fā)。

  • iOS 中的 safari驾孔,為了實現(xiàn)雙擊縮放操作芍秆,在單擊 300ms之后,如果未進行第二次點擊翠勉,則執(zhí)行 click 單擊操作妖啥。也就是說來判斷用戶行為是否為雙擊產(chǎn)生的。但是对碌,在 App 中荆虱,無論是否需要雙擊縮放這種行為,click 單擊都會產(chǎn)生 300ms延遲朽们。

  • 使用 touchstart替換 click

el.addEventListener("touchstart", () => { console.log("ok"); }, false);
  • 在 ```vue`` 中使用

    <button @touchstart="handleTouchstart()">點擊</button>
    
  • 使用fastclick

    import FastClick from 'fastclick';
    
    FastClick.attach(document.body, options);
    

iPhone X系列安全區(qū)域適配問題

  • 頭部劉海兩側(cè)區(qū)域或者底部區(qū)域克伊,出現(xiàn)劉海遮擋文字,或者呈現(xiàn)黑底或白底空白區(qū)域华坦。

  • 設置viewport-fitcover

    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, viewport-fit=cover">
    
    
    • 使用 safe area inset 變量
    /* 適配 iPhone X 頂部填充*/
    @supports (top: env(safe-area-inset-top)){
      body,
      .header{
          padding-top: constant(safe-area-inset-top, 40px);
          padding-top: env(safe-area-inset-top, 40px);
          padding-top: var(safe-area-inset-top, 40px);
      }
    }
    /* 判斷iPhoneX 將 footer 的 padding-bottom 填充到最底部 */
    @supports (bottom: env(safe-area-inset-bottom)){
        body,
        .footer{
            padding-bottom: constant(safe-area-inset-bottom, 20px);
            padding-bottom: env(safe-area-inset-bottom, 20px);
            padding-top: var(safe-area-inset-bottom, 20px);
        }
    }
    
    • safe-area-inset-left:安全區(qū)域距離左邊邊界距離
    • safe-area-inset-right:安全區(qū)域距離右邊邊界距離
    • safe-area-inset-top:安全區(qū)域距離頂部邊界距離
    • safe-area-inset-bottom:安全區(qū)域距離底部邊界距離

    safe-area-inset-top,safe-area-inset-right,safe-area-inset-bottom,safe-area-inset-leftsafe-area-inset-*由四個定義了視口邊緣內(nèi)矩形的top,right,bottomleft的環(huán)境變量組成愿吹,這樣可以安全地放入內(nèi)容,而不會有被非矩形的顯示切斷的風險惜姐。對于矩形視口犁跪,例如普通的筆記本電腦顯示器椿息,其值等于零。對于非矩形顯示器(如圓形表盤坷衍,iPhoneX` 屏幕)寝优,在用戶代理設置的四個值形成的矩形內(nèi),所有內(nèi)容均可見枫耳。

H5 調(diào)試相關方案策略

  • vconsole 控制臺插件

    import Vconsole from 'vconsole'
    
    new Vconsole()
    
  • eruda手機端調(diào)試

  • 只要在我們的```html``文件中寫入下面這些代碼乏矾,在手機上,也能想瀏覽器控制臺一樣進行查看迁杨。

<script src="http://cdn.jsdelivr.net/npm/eruda"></script>
<script>
   eruda.init();
</script>

H5頁面播放視頻

  • H5頁面播放視頻钻心,不全屏播放,在video標簽添加playsinlinex5-playsinline設置為true就行

    <video id="my-video" class="video-js" controls preload="auto" 
                                data-setup=" {} " playsinline="true" x5-playsinline="true"> </video>
    

橫屏適配

  • 很多視口我們要對橫屏和豎屏顯示不同的布局铅协,所以我們需要檢測在不同的場景下給定不同的樣式:

    • JavaScript檢測橫屏
    window.addEventListener('resize',() =>{
        if(window.orientation === 180 || window.orientation === 0) {
            //正常方向或屏幕旋轉(zhuǎn)180度
            console.log('豎屏')
        }
        
        if(window.orientation === 80 || window.orientation === -90) {
            //屏幕順時鐘旋轉(zhuǎn)90度或屏幕逆時針旋轉(zhuǎn)90度
            console.log('橫屏')
        }
    })
    

    CSS檢測橫屏

    @media screen and (orientation:portrait){
      /*豎屏...*/
    }
    
    @media screen and (orientation:landscape){
      /*橫屏...*/
    } 
    

移動端解決0.5px方案

  • 設備像素比:dpr=window.devicePixelRatio捷沸,也就是設備的物理像素與邏輯像素的比值

  • 0.5px 方案

    /*這是css方式*/
    .border { border: 1px solid #999 }
    @media screen and (-webkit-min-device-pixel-ratio: 2) {
        .border { border: 0.5px solid #999 }
    }
    /*ios dpr=2和dpr=3情況下border相差無幾,下面代碼可以省略*/
    @media screen and (-webkit-min-device-pixel-ratio: 3) {
        .border { border: 0.333333px solid #999 }
    }
    
  • viewport + rem

  • 同時通過設置對應viewportrem基準值狐史,這種方式就可以像以前一樣輕松愉快的寫1px了痒给。
    devicePixelRatio=2 時,設置meta

    <meta name="viewport" content="width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
    
    

    實現(xiàn)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>移動端1px問題</title>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
        <meta name="viewport" id="WebViewport"
            content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
        <style>
            html {
                font-size: 11px;
            }
            body {
                padding: 1rem;
            }
            * {
                padding: 0;
                margin: 0;
            }
            .item {
                padding: 1rem;
                border-bottom: 1px solid gray;
                font-size: 1.2rem;
            }
        </style>
        <script>
            var viewport = document.querySelector("meta[name=viewport]");
            var dpr = window.devicePixelRatio || 1;
            var scale = 1 / dpr;
            //下面是根據(jù)設備dpr設置viewport
            viewport.setAttribute(
                "content", +
                "width=device-width," +
                "initial-scale=" +
                scale +
                ", maximum-scale=" +
                scale +
                ", minimum-scale=" +
                scale +
                ", user-scalable=no"
            );
    
            var docEl = document.documentElement;
            var fontsize = 10 * (docEl.clientWidth / 320) + "px";
            docEl.style.fontSize = fontsize;
        </script>
    </head>
    <body>
        <div class="item">border-bottom: 1px solid gray;</div>
        <div class="item">border-bottom: 1px solid gray;</div>
    </body>
    </html>
    

移動端適配方案

  • rem適配

    rem適配的本質(zhì)是布局等比例的縮放骏全,通過動態(tài)設置htmlfont-size來改變rem的大小苍柏。

    <meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
    
  • 引入flexible

    • flexible方案是阿里早期開源的一個移動端適配解決方案,引用flexible后姜贡,我們在頁面上統(tǒng)一使用rem`來布局试吁。

      (function(win, lib) {
          var doc = win.document;
          var docEl = doc.documentElement;
          var metaEl = doc.querySelector('meta[name="viewport"]');
          var flexibleEl = doc.querySelector('meta[name="flexible"]');
          var dpr = 0;
          var scale = 0;
          var tid;
          var flexible = lib.flexible || (lib.flexible = {});
          
          if (metaEl) {
              console.warn('將根據(jù)已有的meta標簽來設置縮放比例');
              var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
              if (match) {
                  scale = parseFloat(match[1]);
                  dpr = parseInt(1 / scale);
              }
          } else if (flexibleEl) {
              var content = flexibleEl.getAttribute('content');
              if (content) {
                  var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
                  var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
                  if (initialDpr) {
                      dpr = parseFloat(initialDpr[1]);
                      scale = parseFloat((1 / dpr).toFixed(2));    
                  }
                  if (maximumDpr) {
                      dpr = parseFloat(maximumDpr[1]);
                      scale = parseFloat((1 / dpr).toFixed(2));    
                  }
              }
          }
      
          if (!dpr && !scale) {
              var isAndroid = win.navigator.appVersion.match(/android/gi);
              var isIPhone = win.navigator.appVersion.match(/iphone/gi);
              var devicePixelRatio = win.devicePixelRatio;
              if (isIPhone) {
                  // iOS下,對于2和3的屏鲁豪,用2倍的方案潘悼,其余的用1倍方案
                  if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                
                      dpr = 3;
                  } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
                      dpr = 2;
                  } else {
                      dpr = 1;
                  }
              } else {
                  // 其他設備下律秃,仍舊使用1倍的方案
                  dpr = 1;
              }
              scale = 1 / dpr;
          }
      
          docEl.setAttribute('data-dpr', dpr);
          if (!metaEl) {
              metaEl = doc.createElement('meta');
              metaEl.setAttribute('name', 'viewport');
              metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
              if (docEl.firstElementChild) {
                  docEl.firstElementChild.appendChild(metaEl);
              } else {
                  var wrap = doc.createElement('div');
                  wrap.appendChild(metaEl);
                  doc.write(wrap.innerHTML);
              }
          }
      
          function refreshRem(){
              var width = docEl.getBoundingClientRect().width;
              if (width / dpr > 540) {
                  width = 540 * dpr;
              }
              var rem = width / 10;
              docEl.style.fontSize = rem + 'px';
              flexible.rem = win.rem = rem;
          }
      
          win.addEventListener('resize', function() {
              clearTimeout(tid);
              tid = setTimeout(refreshRem, 300);
          }, false);
          win.addEventListener('pageshow', function(e) {
              if (e.persisted) {
                  clearTimeout(tid);
                  tid = setTimeout(refreshRem, 300);
              }
          }, false);
      
          if (doc.readyState === 'complete') {
              doc.body.style.fontSize = 12 * dpr + 'px';
          } else {
              doc.addEventListener('DOMContentLoaded', function(e) {
                  doc.body.style.fontSize = 12 * dpr + 'px';
              }, false);
          }
          
      
          refreshRem();
      
          flexible.dpr = win.dpr = dpr;
          flexible.refreshRem = refreshRem;
          flexible.rem2px = function(d) {
              var val = parseFloat(d) * this.rem;
              if (typeof d === 'string' && d.match(/rem$/)) {
                  val += 'px';
              }
              return val;
          }
          flexible.px2rem = function(d) {
              var val = parseFloat(d) / this.rem;
              if (typeof d === 'string' && d.match(/px$/)) {
                  val += 'rem';
              }
              return val;
          }
      
      })(window, window['lib'] || (window['lib'] = {}));
      
    • 使用vw爬橡,vh布局

    • vh、vw方案即將視覺視口寬度 window.innerWidth和視覺視口高度 window.innerHeight 等分為 100 份棒动。

    • 如果視覺視口為 375px糙申,那么 1vw=3.75px,這時 UI給定一個元素的寬為 75px(設備獨立像素)船惨,我們只需要將它設置為 75/3.75=20vw柜裸。

    • 這里的比例關系我們也不用自己換算,我們可以使用 PostCSSpostcss-px-to-viewport 插件幫我們完成這個過程粱锐。寫代碼時疙挺,我們只需要根據(jù) UI給的設計圖寫 px單位即可。

      module.exports = {
        plugins: [
          require('autoprefixer'),
          require('postcss-import'),
          require('postcss-url'),
          require('postcss-preset-env'),
          require('postcss-aspect-ratio-mini'),
          require('postcss-write-svg'),
          require('postcss-px-to-viewport')({
            viewportWidth: 750,
            viewportHeight: 1334,
            unitPrecision: 3,
            viewportUnit: 'vw',
            selectorBlackList: [ '.ignore', '.hairlines', '.footer' ],
            minPixelValue: 1,
            mediaQuery: true
          }),
          require('cssnano')
        ]
      }
      
      

快速生成HTML代碼結(jié)構(gòu)

#page>div.logo+ul#navigation>li*5>a{Item $}

可以轉(zhuǎn)換為

<div id="page">
    <div class="logo"></div>
    <ul id="navigation">
        <li><a href="">Item 1</a></li>
        <li><a href="">Item 2</a></li>
        <li><a href="">Item 3</a></li>
        <li><a href="">Item 4</a></li>
        <li><a href="">Item 5</a></li>
    </ul>
</div>
  • 使用>運算符將元素相互嵌套

    div>ul>li 生成
    <div>
        <ul>
            <li></li>
        </ul>
    </div>
    
  • 使用+運算符將元素彼此放置在同一水平上:

    div+p+bq 生成
    <div></div>
    <p></p>
    <blockquote></blockquote>
    
  • 使用括號將復雜縮寫的子樹分組

    div>(header>ul>li*2>a)+footer>p  生成
    <div>
        <header>
            <ul>
                <li><a href=""></a></li>
                <li><a href=""></a></li>
            </ul>
        </header>
        <footer>
            <p></p>
        </footer>
    </div>
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怜浅,一起剝皮案震驚了整個濱河市铐然,隨后出現(xiàn)的幾起案子蔬崩,更是在濱河造成了極大的恐慌,老刑警劉巖搀暑,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沥阳,死亡現(xiàn)場離奇詭異,居然都是意外死亡自点,警方通過查閱死者的電腦和手機桐罕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來桂敛,“玉大人功炮,你說我怎么就攤上這事〔嚎校” “怎么了死宣?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碴开。 經(jīng)常有香客問我毅该,道長,這世上最難降的妖魔是什么潦牛? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任眶掌,我火速辦了婚禮,結(jié)果婚禮上巴碗,老公的妹妹穿的比我還像新娘朴爬。我一直安慰自己,他們只是感情好橡淆,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布召噩。 她就那樣靜靜地躺著,像睡著了一般逸爵。 火紅的嫁衣襯著肌膚如雪具滴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天师倔,我揣著相機與錄音构韵,去河邊找鬼。 笑死趋艘,一個胖子當著我的面吹牛疲恢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瓷胧,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼显拳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了搓萧?” 一聲冷哼從身側(cè)響起杂数,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤遇八,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后耍休,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體刃永,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年羊精,在試婚紗的時候發(fā)現(xiàn)自己被綠了斯够。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡喧锦,死狀恐怖读规,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情燃少,我是刑警寧澤束亏,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站阵具,受9級特大地震影響碍遍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜阳液,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一怕敬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帘皿,春花似錦东跪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至曹动,卻和暖如春斋日,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仁期。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工桑驱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留竭恬,地道東北人跛蛋。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像痊硕,于是被迫代替她去往敵國和親赊级。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 移動端適配橡伞,是我們在開發(fā)中經(jīng)常會遇到的,這里面可能會遇到非常多的問題: 1px問題 UI圖完美適配方案 iPhon...
    Vicky丶Amor閱讀 8,840評論 4 19
  • 導讀 移動端適配,是我們在開發(fā)中經(jīng)常會遇到的羡洛,這里面可能會遇到非常多的問題: 1px問題 UI圖完美適配方案 iP...
    精神蛙閱讀 1,079評論 0 2
  • 導讀 移動端適配欲侮,是我們在開發(fā)中經(jīng)常會遇到的崭闲,這里面可能會遇到非常多的問題: 1px問題 UI圖完美適配方案 iP...
    編程鴨閱讀 1,809評論 0 0
  • 移動互聯(lián)網(wǎng)發(fā)展的如火如荼,這對前端工程師要求就更高了威蕉,移動端適配也就成為了重要的問題之一刁俭。先說一下涉及到的基本的概...
    gaoxuerong閱讀 573評論 0 1
  • 一、使用真實手機測試未發(fā)布網(wǎng)頁的方法 方法① 在虛擬機中搭建xampp韧涨,將文件通過FTP傳到虛擬機牍戚,在一個局域網(wǎng)中...
    fastwe閱讀 718評論 0 0