43. vue的移动端屏幕适配

作者: yaoyao妖妖 | 来源:发表于2018-11-02 13:44 被阅读24次

    1. 首先是适配基础知识的补充,主要是利用rem

    http://caibaojian.com/flexible-js.html

    1.2 适配的原理如下

    a ) 首先利用flexible.js确定适配基础dpr和font-size
    b ) 然后使用px2rem2-loader实现px转化为rem的值,(rem的值是由HTML的font-size来确定的) 按照6s设计图来配置相关参数

    2. 然后具体的实现方案

    1. 首先将index.html修改如下(flexible.js的内容移动到这里了)
    <!DOCTYPE html>
    <html>
    
    <head>
     <meta charset="utf-8">
     <meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
     <script lang="javascript">
       'use strict';
       (function(win, lib) {
           let doc = win.document;
           let docEl = doc.documentElement;
           let metaEl = doc.querySelector('meta[name="viewport"]');
           let flexibleEl = doc.querySelector('meta[name="flexible"]');
           let dpr = 0;
           let scale = 0;
           let tid;
           let flexible = lib.flexible || (lib.flexible = {});
    
           if (metaEl) {
               //console.warn('将根据已有的meta标签来设置缩放比例');
               let match = metaEl.getAttribute('content').match(/initial-scale=([\d.]+)/);
               if (match) {
                   scale = parseFloat(match[1]);
                   dpr = parseInt(1 / scale);
               }
           } else if (flexibleEl) {
               let content = flexibleEl.getAttribute('content');
               if (content) {
                   let initialDpr = content.match(/initial-dpr=([\d.]+)/);
                   let 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) {
               let isAndroid = win.navigator.appVersion.match(/android/gi);
               let isIPhone = win.navigator.appVersion.match(/iphone/gi);
               let 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 {
                   let wrap = doc.createElement('p');
                   wrap.appendChild(metaEl);
                   doc.write(wrap.innerHTML);
               }
           }
    
           function refreshRem() {
               let width = docEl.getBoundingClientRect().width;
               if (width / dpr > 540) {
                   width = 540 * dpr;
               }
               let 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) {
               let val = parseFloat(d) * this.rem;
               if (typeof d === 'string' && d.match(/rem$/)) {
                   val += 'px';
               }
               return val;
           }
           flexible.px2rem = function(d) {
               let val = parseFloat(d) / this.rem;
               if (typeof d === 'string' && d.match(/px$/)) {
                   val += 'rem';
               }
               return val;
           }
    
         })(window, window['lib'] || (window['lib'] = {}));
     </script>
     <title>app的标题</title>
    </head>
    
    <body>
     <div id="app"></div>
     <!-- built files will be auto injected -->
    </body>
    
    </html>
    
    注:遇到的问题

    网上找到很多的博客的内容是将flexible.js单独的提出去,但是在实际的操作中发现会导致在通过浏览器的按钮刷新的时候导致适配出现错误,所以解决方案就是是把flexible.js的代码移到了index.html内部,没有采用静态链接的方式。

    知识点补充:flexible.js 主要做了下面的几件事

    动态改写<meta>标签
    给<html>元素添加data-dpr属性,并且动态改写data-dpr的值
    给<html>元素添加font-size属性,并且动态改写font-size的值

    1. 然后接着按照上面文档的设置即可(从4开始配置)https://www.cnblogs.com/xiaobaibubai/p/8528744.html
      这个步骤是为了将px转化为rem。
      知识点补充:使用Flexible实现手淘H5页面的终端适配
      https://github.com/amfe/article/issues/17?utm_source=caibaojian.com

    相关文章

      网友评论

        本文标题:43. vue的移动端屏幕适配

        本文链接:https://www.haomeiwen.com/subject/digqxqtx.html