详解Vue-cli3.X使用px2rem遇到的问题


Posted in Javascript onAugust 09, 2019

把项目脚手架升级为cli3.X了以后,模板简洁了很多,运行起来也更加快速。但是也随之而来是某些兼容问题。比如我们要在项目钟使用px2rem来计算设计稿的时候,我们不能像以前老的脚手架那样操作了。那我们应该来如何设置呢?

首先,我们应该用NPM来安装postcss-px2rem

npm i postcss-plugin-px2rem --save -dev

然后我们需要在vue.config.js中创建一个配置。由于在vue-cli3.X中。去掉了build和config文件夹。所有的配置都放到了vue.config.js,然而这个文件脚手架并没有生成,所以需要手动在项目的根目录创建一个文件

在vue.config.js里配置

module.exports = {
  lintOnSave: true,
  css: {
    loaderOptions: {
      postcss: {
        plugins: [
          require('postcss-plugin-px2rem')({
            rootValue:75,      // 新版本的是这个值
            mediaQuery: false, //(布尔值)允许在媒体查询中转换px。
            minPixelValue: 3 //设置要替换的最小像素值(3px会被转rem)。 默认 0
          }),
        ]
      }
    }
  },
}

这里需要说明一点。网上搜的一堆教程都强调应该增加remUnit来设置rem的计算标准。但是其实在新版后,这个值换成了rootValue这个。例如你设计稿为750的宽度标准,那么这里的值设置为75则可。

接下来还有一个工作。由于rem是根据根字体的大小来作为基准值的,然而我们的移动设备屏幕大小以及有些屏幕为视网膜屏的,会是普通屏幕的2倍,所以这个基准值我们需要根据不同设备来进行计算。这里我们在src/plugins下新建一个rem.js文件(代码如下)。

(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;
    }
    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'] = {}));

然后在main.js里面引入该文件

import './plugins/rem.js'

这样,我们的工作就完成了。可以直接在css里面写px的绝对值。

详解Vue-cli3.X使用px2rem遇到的问题

详解Vue-cli3.X使用px2rem遇到的问题

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
锋利的jQuery 要点归纳(三) jQuery中的事件和动画(下:动画篇)
Mar 24 Javascript
JQuery 选择器、过滤器介绍
Feb 14 Javascript
24款非常有用的 jQuery 插件分享
Apr 06 Javascript
使用GruntJS链接与压缩多个JavaScript文件过程详解
Aug 02 Javascript
让checkbox不选中即将选中的checkbox不选中
Jul 11 Javascript
JavaScript实现cookie的写入、读取、删除功能
Nov 05 Javascript
node.js中fs.stat与fs.fstat的区别详解
Jun 01 Javascript
vue获取当前激活路由的方法
Mar 17 Javascript
jQuery+ajax实现动态添加表格tr td功能示例
Apr 23 jQuery
iconfont的三种使用方式详解
Aug 05 Javascript
vue使用ajax获取后台数据进行显示的示例
Aug 09 Javascript
Vuex 模块化使用详解
Jul 31 Javascript
微信小程序引入模块中wxml、wxss、js的方法示例
Aug 09 #Javascript
小程序Request的另类用法详解
Aug 09 #Javascript
一篇文章弄懂javascript中的执行栈与执行上下文
Aug 09 #Javascript
vue中组件通信的八种方式(值得收藏!)
Aug 09 #Javascript
Vue全局loading及错误提示的思路与实现
Aug 09 #Javascript
使用Vue CLI创建typescript项目的方法
Aug 09 #Javascript
详解vue beforeRouteEnter 异步获取数据给实例问题
Aug 09 #Javascript
You might like
PHP 实现多服务器共享 SESSION 数据
2009/08/15 PHP
PHP为表单获取的URL 地址预设 http 字符串函数代码
2010/05/26 PHP
详解PHP序列化反序列化的方法
2015/10/27 PHP
使用PHP uniqid函数生成唯一ID
2015/11/18 PHP
Laravel的Auth验证Token验证使用自定义Redis的例子
2019/09/30 PHP
jquery中的$(document).ready()与window.onload的区别
2009/11/18 Javascript
jqTransform form表单美化插件使用方法
2012/07/05 Javascript
JS延时提示框实现方法详解
2015/11/26 Javascript
vue 项目常用加载器及配置详解
2018/01/22 Javascript
浅谈AngularJS中$http服务的简单用法
2018/05/15 Javascript
轻量级富文本编辑器wangEditor结合vue使用方法示例
2018/10/10 Javascript
vue-router懒加载速度缓慢问题及解决方法
2018/11/25 Javascript
微信小程序实现发送验证码按钮效果
2018/12/20 Javascript
微信小程序实现点击图片放大预览
2019/10/21 Javascript
vue-cli或vue项目利用HBuilder打包成移动端app操作
2020/07/29 Javascript
vue项目如何监听localStorage或sessionStorage的变化
2021/01/04 Vue.js
使用python实现strcmp函数功能示例
2014/03/25 Python
python版本坑:md5例子(python2与python3中md5区别)
2017/06/20 Python
Python创建普通菜单示例【基于win32ui模块】
2018/05/09 Python
python3实现小球转动抽奖小游戏
2020/04/15 Python
Python中typing模块与类型注解的使用方法
2019/08/05 Python
Python拆分大型CSV文件代码实例
2019/10/07 Python
Python基于stuck实现scoket文件传输
2020/04/02 Python
Python ini文件常用操作方法解析
2020/04/26 Python
Python 执行矩阵与线性代数运算
2020/08/01 Python
美国气象仪器、花园装饰和墙壁艺术商店:Wind & Weather
2019/05/29 全球购物
进程的查看和调度分别使用什么命令
2013/12/14 面试题
急诊科护士自我鉴定
2013/10/14 职场文书
财务总监管理职责范文
2014/03/09 职场文书
教研活动总结
2014/04/28 职场文书
2014民事授权委托书范本
2014/09/29 职场文书
2014年领导班子工作总结
2014/12/11 职场文书
销售工作决心书
2015/02/04 职场文书
2015最新学生自我评价范文
2015/03/03 职场文书
图书借阅制度范本
2015/08/06 职场文书
网络安全倡议书(3篇)
2019/09/18 职场文书