详解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 相关文章推荐
将HTML自动转为JS代码
Jun 26 Javascript
基于jquery的模态div层弹出效果
Aug 21 Javascript
JS控制图片等比例缩放的示例代码
Dec 24 Javascript
js动态删除div元素基本思路及实现代码
May 08 Javascript
函数式 JavaScript(一)简介
Jul 07 Javascript
AngularJS教程之环境设置
Aug 16 Javascript
用Angular实时获取本地Localstorage数据,实现一个模拟后台数据登入的效果
Nov 09 Javascript
canvas+gif.js打造自己的数字雨头像的示例代码
Oct 26 Javascript
JS实现的文字间歇循环滚动效果完整示例
Feb 13 Javascript
Node.js 利用cheerio制作简单的网页爬虫示例
Mar 01 Javascript
对Vue.js之事件的绑定(v-on: 或者 @ )详解
Sep 15 Javascript
vue使用showdown并实现代码区域高亮的示例代码
Oct 17 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+JS+rsa数据加密传输实现代码
2011/03/23 PHP
PHP中使用sleep函数实现定时任务实例分享
2014/08/21 PHP
thinkPHP连接sqlite3数据库的实现方法(附Thinkphp代码生成器下载)
2016/05/27 PHP
PHP封装cURL工具类与应用示例
2019/07/01 PHP
JCalendar 日历控件 v1.0 beta[兼容IE&Firefox] 有文档和例子
2007/05/30 Javascript
JavaScript 在各个浏览器中执行的耐性
2009/04/06 Javascript
JS模拟的QQ面板上的多级可展开的菜单
2009/10/10 Javascript
这段js代码得节约你多少时间
2011/12/20 Javascript
jquery select动态加载选择(兼容各种浏览器)
2013/02/01 Javascript
JS验证邮件地址格式方法小结
2015/12/01 Javascript
JavaScript代码实现左右上下自动晃动自动移动
2016/04/08 Javascript
javascript闭包概念简单解析(推荐)
2016/06/03 Javascript
js中小数向上取整数,向下取整数,四舍五入取整数的实现(必看篇)
2017/02/13 Javascript
jQuery自定义元素右键点击事件(实现案例)
2017/04/28 jQuery
Vue实现virtual-dom的原理简析
2017/07/10 Javascript
Vue 项目中遇到的跨域问题及解决方法(后台php)
2018/03/28 Javascript
vue-router二级导航切换路由及高亮显示的实现方法
2019/07/10 Javascript
Vue两个版本的区别和使用方法(更深层次了解)
2020/02/16 Javascript
[01:58]最残酷竞争 2016国际邀请赛中国区预选赛积分循环赛回顾
2016/06/28 DOTA
[04:40]DOTA2-DPC中国联赛1月26日Recap集锦
2021/03/11 DOTA
python处理xml文件的方法小结
2017/05/02 Python
手把手教你用python抢票回家过年(代码简单)
2018/01/21 Python
使用Python的Dataframe取两列时间值相差一年的所有行方法
2018/07/10 Python
在PyCharm中实现关闭一个死循环程序的方法
2018/11/29 Python
Python坐标线性插值应用实现
2019/11/13 Python
python logging.basicConfig不生效的原因及解决
2020/02/20 Python
Python 实现将某一列设置为str类型
2020/07/14 Python
python如何用matplotlib创建三维图表
2021/01/26 Python
美国滑雪板和装备购物网站:Skis.com
2018/12/20 全球购物
俄罗斯隐形眼镜和眼镜在线商店:Cronos
2020/06/02 全球购物
小学生期末自我鉴定
2014/01/19 职场文书
电气个人求职信范文
2014/02/04 职场文书
公司表扬稿范文
2015/05/05 职场文书
工厂员工辞职信范文
2015/05/12 职场文书
Python趣味实战之手把手教你实现举牌小人生成器
2021/06/07 Python
HTML CSS 一个标签实现带动画的抖音LOGO
2022/04/26 HTML / CSS