详解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 相关文章推荐
防止动态加载JavaScript引起的内存泄漏问题
Oct 08 Javascript
JavaScript接口实现代码 (Interfaces In JavaScript)
Jun 11 Javascript
用JS判断IE版本的代码 超管用!
Aug 09 Javascript
基于JQuery的抓取博客园首页RSS的代码
Dec 01 Javascript
使用按钮控制以何种方式打开新窗口的属性介绍
Dec 17 Javascript
Jquery chosen动态设置值实例介绍
Aug 08 Javascript
你未必知道的JavaScript和CSS交互的5种方法
Apr 02 Javascript
jquery实现点击文字可编辑并修改保存至数据库
Apr 15 Javascript
js表头排序实现方法
Jan 16 Javascript
第二章之Bootstrap 页面排版样式
Apr 25 Javascript
Bootstrap3 模态框使用实例
Feb 22 Javascript
layui写后台表格思路和赋值用法详解
Nov 14 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使用curl抓取qq空间的访客信息示例
2014/02/28 PHP
Yii框架中memcache用法实例
2014/12/03 PHP
PHP中的命名空间相关概念浅析
2015/01/22 PHP
php设计模式之单例模式实例分析
2015/02/25 PHP
Windows下编译PHP5.4和xdebug全记录
2015/04/03 PHP
laravel实现上传图片的两种方式小结
2019/10/12 PHP
tp5.1 框架数据库-数据集操作实例分析
2020/05/26 PHP
初学js 新节点的创建 删除 的步骤
2011/07/04 Javascript
jQuery插件原来如此简单 jQuery插件的机制及实战
2012/02/07 Javascript
上传的js验证(图片/文件的扩展名)
2013/04/25 Javascript
js控制当再次点击按钮时的间隔时间
2014/06/03 Javascript
JQuery表格拖动调整列宽效果(自己动手写的)
2014/09/01 Javascript
Bootstrap零基础入门教程(二)
2016/07/18 Javascript
通过BootStrap-select插件 js jQuery控制select属性变化
2017/01/03 Javascript
nodejs和C语言插入mysql数据库乱码问题的解决方法
2017/04/14 NodeJs
微信小程序网络请求wx.request详解及实例
2017/05/18 Javascript
jQuery 控制文本框自动缩小字体填充
2017/06/16 jQuery
分享19个JavaScript 有用的简写写法
2017/07/07 Javascript
详解react-native WebView 返回处理(非回调方法可解决)
2018/02/27 Javascript
javascript中floor使用方法总结
2019/02/02 Javascript
vue简单封装axios插件和接口的统一管理操作示例
2020/02/02 Javascript
python网络编程学习笔记(二):socket建立网络客户端
2014/06/09 Python
Python3安装Pymongo详细步骤
2017/05/26 Python
Python 保持登录状态进行接口测试的方法示例
2019/08/06 Python
Python面向对象之多态原理与用法案例分析
2019/12/30 Python
Python3以GitHub为例来实现模拟登录和爬取的实例讲解
2020/07/30 Python
中国一家专注拼团的社交购物网站:拼多多
2018/06/13 全球购物
美国肌肉和力量商店:Muscle & Strength
2019/06/22 全球购物
kfc实习自我鉴定
2013/12/14 职场文书
函授毕业生自我鉴定范文
2014/03/25 职场文书
幼儿园中班上学期评语
2014/04/18 职场文书
测量员岗位职责
2015/02/14 职场文书
学雷锋献爱心活动总结
2015/05/11 职场文书
交通事故被告代理词
2015/05/23 职场文书
Mysql中常用的join连接方式
2022/05/11 MySQL
Redis实现短信验证码登录的示例代码
2022/06/14 Redis