vue + (webpack/ vite) pc 端页面适配

关于vue 在pc端的页面适配做一个比较详细的汇总

因为之前自己用的都是vue2 + webpack 所以对于这个的适配比较熟练  后来又用到了vue3+ vite, 两者关于pc端页面适配的流程差别不大,下面做一个汇总 (萌新笔记)

1. vue2 + webpake

首先需要安装两个插件 (也可以只安装第一个,具体原因下面说 )

npm install postcss-px2rem --save-dev

表示将px转换为rem   因为我用的这个pc端适配的方法核心原理是rem转换

npm i lib-flexible --save-dev     

这个是阿里用来做设备适配的一个插件,但是当设备宽度较大时,他就会恒定根标签的font-size为54px,所以我们可以一会对这个js文件进行修改,或者是直接自己在其他目录下新建一个,引用自己新建的就好。

安装之后的第一件事就是找到我们的flexible.js 文件,进行修改,这里我可以我直接发源码就好了,这个也是参考了网上的一些代码,(我自己一开始肯定写不出来的,后来看了很久才看明白也是,就是借鉴使用)

我们可以在这个位置找到flexble.js   在node_module中找到这个文件

vue + (webpack/ vite) pc 端页面适配_第1张图片

 进入之后进行修改 修改为一下代码

;(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('将根据已有的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;
            //变更
            width = width * 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'] = {}));

其实核心部分就是修改了这里

 function refreshRem(){
        var width = docEl.getBoundingClientRect().width;
        if (width / dpr > 540) {
            // width = 540 * dpr;
            //变更
            width = width * dpr;
        }
        var rem = width / 10;
        docEl.style.fontSize = rem + 'px';
        flexible.rem = win.rem = rem;
    }

之前的js 中,不适用与pc设备,只使用与移动设备,对于pc端来讲,html的font-size会被固定为54px,而1rem是等于这个大小的,所以对于pc端来讲就会失去意义,我们设置之后就是,该数值会恒定为设备宽度的1/10,这个就是使用rem的老前辈们的习惯,将这些完成以后,我们可以在main.js中引入我们写好的js,如果是修改原文件,就直接

import 'lib-flexible'

如果是你是自己新建的,就引入自己的。

然后我们可以开始一个小实验测试一下。(使用rem)

这里我随便创建一个盒子(id:test) 然后加上样式

#test{
  width: 5rem;
  height: 5rem;
  background-color: red;
}

我们看一下效果

因为我们的宽度为5rem(1rem=1/10总宽度) 所以对应的盒子宽度为设备一半,那我们修改设备宽度看一下结果

可以看到盒子可以自适应的改变自己的宽度(还是总设备的一半),原理就是每次设备宽度修改,flexblie.js会帮助我们修改根标签的font-size 导致1rem总是等于视口宽度1/10

但是现在的问题是 我们不能总是写rem,因为拿到的设计图一般是px的,自己计算的话

T rem=(N px/ M  ) (1rem=Mpx)  这显然很麻烦 所以就用上了我们第一个插件 , 这个插件的作用就是将px转换为rem 这个是webpack打包时loader会发挥的作用,这个就不细谈了。

用法比较简单,首先打开自己的vue.config.js,在最外面的目录(与package.json同级),如果没有的话就自己创建一个。

打开之后加入如下代码

const px2rem = require('postcss-px2rem')
const postcss = px2rem({
    remUnit: 192 // 基准值
})
module.exports = {
    css: {
        loaderOptions: {
            postcss: {
                plugins: [
                    postcss
                ]
            }
        }
    },
    devServer: {
        port: 3000
    },
}

最后那个devServer是我自己改的端口可以无视掉,需要注意的就是前面的remUnit=192 ,表示1rem=192px 因为我们普遍的设计图为1920*1080  所以1/10宽度为192

全都完成之后我们可以看效果,还是刚刚的盒子,现在我修改css

#test{
  width: 400px;
  height: 400px;
  background-color: red;
}

然后看效果

修改设备宽度

可以看到盒子意见完成了自适应。以上是关于vue+webpack 使用rem适配的方法。

2. vue+vite  

这个和上面的操作基本都是一样的,区别只有 vite 配置时不要再vue.config.js中使用第一个插件,这是webpack的使用方法,vite我们需要再同一层级下创建postcss.config.js

然后加入一下代码

const px2rem = require('postcss-px2rem')
const postcss = px2rem({
    remUnit: 190 // 基准值
})
module.exports = {
    plugins: {
        postcss
    }
}

就可以同样的完成pc端的适配,效果与1中相同。

一些注意事项:

1.  内联样式中的px是无法被适配为rem的

例如

2. 直接按上述方法使用可能会对第三方ui 例如element-ui的显示造成影响 

这里提供再postcss中的另一种写法

module.exports = {
  "plugins": {
    "postcss-pxtorem": {
      rootValue: 192,
      propList: ['*'],
      selectorBlackList: [
        'ant'
      ]
    }
  }
}

这样写的话就可以避免对ui库的影响  如果用的是webpack  直接在px2rem-loader属性里加上除去node_modules即可

exclude:/node_modules/

 

(纯萌新笔记)

你可能感兴趣的