webpack实现一个行内样式px转vw的loader示例


Posted in Javascript onSeptember 13, 2018

需求

自从有了postcss来处理css文件,我们可以快速进行网站适配的开发,只需要改改参数,样式按照设计稿的px写,webpack编译自动转换成rem或者vw等。

但是,标签内的px怎么办呢?postcss并不提供转换这个的功能。

探索

启动思路

我正在做一个vue项目,刚好想要实现上面提到的需求,例如下面的例子

<h3 style="font-size: 28px;margin-top: 10px" width="500px">Test</h3>

我希望他能根据我设置的基准值自动转换成vw。

<h3 width="00vw" style="font-size: 00vw; margin-top: 00vw;">Test</h3>

要想实现这样一个东西,离不开编译工具webpack,webpack有loader、plugin,用什么好呢?通过找资料,我从一篇px转rem的文章中得到了提示 react内联样式使用webpack将px转rem

没错,就是webpack-loader

写一个webpack loader,在webpack编译阶段,读取vue文件里面的内容,通过正则识别出需要转换的像素px,再通过公式转换成vw。

开始行动

1、了解loader的实现原理

写一个loader很简单,传入source,干些坏事,干完之后,返回处理过的source。source对应的是每一个通过loader匹配到的文件。

module.exports = function (source) {
 // 干些坏事
 return source
}

2、如何让loader干坏事

先看一个简单的vue文件,通常分为3部分,<template>、<script>、<style>

<template>
 <div>
  <h3 style="font-size: 28px;margin-top: 10px" width="500px">Test</h3>
 </div>
</template>

<script>
 export default {
  name: '',
  components: {},
  created () {},
  mounted () {},
  methods: {}
 }
</script>

<style lang="less">
 h3 {
  font-size: 20px;
 }
</style>

我们知道<style>部分已经有postcss会进行转换处理,所以我把重点放到了<template>内部的 “00px”。

其实source对应的就是这样一个vue文件,该例子中有28px、10px、500px是需要转换的目标,首先用正则把他们都找出来。

先把template部分提出来,防止把style部分也转换了

const template = /<template>([\s\S]+)<\/template>/gi

// 匹配出来的部分
<template>
 <div>
  <h3 style="font-size: 28px;margin-top: 10px" width="500px">Test</h3>
 </div>
</template>

匹配px的正则

const ZPXRegExp = /(\d+)px/

对template里面的px进行转换

module.exports = function (source) {
 let _source = ''
 // 如果当前的source里面存在template
 if (template.test(source)) {
  // 匹配template部分
  _source = source.match(template)[0]
 }
 // 匹配出template里面的px
 let pxGlobalRegExp = new RegExp(ZPXRegExp.source, 'ig')
 if (pxGlobalRegExp.test(_source)) {
  // px转换vw,核心部分
  let $_source = _source.replace(pxGlobalRegExp, createPxReplace(defaults.viewportWidth, defaults.minPixelValue, defaults.unitPrecision, defaults.viewportUnit))
  // 转换之后替换回source中,返回函数值
  return source.replace(template, $_source)
 } else {
  //没有就不转,直接返回
  return source
 }
}

px转vw的公式

我使用的是 postcss-px-to-viewport 内部实现的转换公式

function createPxReplace (viewportSize, minPixelValue, unitPrecision, viewportUnit) {
 // 不用好奇$0, $1是怎么来的,他们是replace第二个参数提供的
 return function ($0, $1) {
  if (!$1) return
  var pixels = parseFloat($1)
  if (pixels <= minPixelValue) return
  return toFixed((pixels / viewportSize * 100), unitPrecision) + viewportUnit
 }
}
function toFixed (number, precision) {
 var multiplier = Math.pow(10, precision + 1),
  wholeNumber = Math.floor(number * multiplier)
 return Math.round(wholeNumber / 10) * 10 / multiplier
}

使用和postcss-px-to-viewport类似的配置

一个基本的配置大概包含这些信息

let defaultsProp = {
 unitToConvert: 'px',
 viewportWidth: 750,
 unitPrecision: 5,
 viewportUnit: 'vw',
 fontViewportUnit: 'vw',
 minPixelValue: 1
}

给webpack-loader加上option

const loaderUtils = require('loader-utils')

const opts = loaderUtils.getOptions(this)
const defaults = Object.assign({}, defaultsProp, opts)

好了,现在我们实现了一个可以干坏事的loader,?不,是做好事!

我们来看看转换成果

<h3 width="66.66667vw" style="font-size: 3.73333vw; margin-top: 1.33333vw;">Test</h3>

反思

虽然实现了我一开始的需求,但是心里总是不淡定,因为还些坑没有想明白,后续如果想明白了,再进行完善。

源码

style-vw-loader

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

Javascript 相关文章推荐
JS文本框默认值处理详解
Jul 10 Javascript
JS 页面计时器示例代码
Oct 28 Javascript
JS页面延迟执行一些方法(整理)
Nov 11 Javascript
jQuery判断复选框是否勾选的原理及示例
May 21 Javascript
Javascript学习笔记之 函数篇(一) : 函数声明和函数表达式
Jun 24 Javascript
javascript实现网页背景烟花效果的方法
Aug 06 Javascript
使用JSON作为函数的参数的优缺点
Oct 27 Javascript
EasyUI折叠表格层次显示detailview详解及实例
Dec 28 Javascript
JavaScript实现三级联动菜单效果
Aug 16 Javascript
js中对象与对象创建方法的各种方法
Feb 27 Javascript
解决antd日期选择组件,添加value就无法点击下一年和下一月问题
Oct 29 Javascript
解决elementui表格操作列自适应列宽
Dec 28 Javascript
vue项目开发中setTimeout等定时器的管理问题
Sep 13 #Javascript
详解react内联样式使用webpack将px转rem
Sep 13 #Javascript
详解webpack 热更新优化
Sep 13 #Javascript
Vue中使用 setTimeout() setInterval()函数的问题
Sep 13 #Javascript
Angularjs之ngModel中的值验证绑定方法
Sep 13 #Javascript
在小程序/mpvue中使用flyio发起网络请求的方法
Sep 13 #Javascript
解决angular2在双向数据绑定时[(ngModel)]无法使用的问题
Sep 13 #Javascript
You might like
async和DOM Script文件加载比较
2014/07/20 PHP
PHP中Socket连接及读写数据超时问题分析
2016/07/19 PHP
php使用crypt()函数进行加密
2017/06/08 PHP
PHP PDO和消息队列的个人理解与应用实例分析
2019/11/25 PHP
基于prototype的validation.js发布2.3.4新版本,让你彻底脱离表单验证的烦恼
2006/12/06 Javascript
Ext.MessageBox工具类简介
2009/12/10 Javascript
利用google提供的API(JavaScript接口)获取网站访问者IP地理位置的代码详解
2010/07/24 Javascript
zeroclipboard复制到剪切板的flash
2010/08/04 Javascript
jquery+html5时钟特效代码分享(可设置闹钟并且语音提醒)
2020/03/30 Javascript
js实现iframe框架取值的方法(兼容IE,firefox,chrome等)
2015/11/26 Javascript
用nodejs的实现原理和搭建服务器(动态)
2016/08/10 NodeJs
js实现关闭网页出现是否离开提示
2017/12/07 Javascript
浅谈Vue SPA 首屏加载优化实践
2017/12/15 Javascript
JavaScript实现多重继承的方法分析
2018/01/09 Javascript
JavaScript分步实现一个出生日期的正则表达式
2018/03/22 Javascript
Vuex mutitons和actions初使用详解
2019/03/04 Javascript
详解vue-cli+es6引入es5写的js(两种方法)
2019/04/19 Javascript
基于iview的router常用控制方式
2019/05/30 Javascript
Python实现的石头剪子布代码分享
2014/08/22 Python
Python3实现的判断环形链表算法示例
2019/03/07 Python
Python抓新型冠状病毒肺炎疫情数据并绘制全国疫情分布的代码实例
2020/02/05 Python
Python3标准库之functools管理函数的工具详解
2020/02/27 Python
Python获取对象属性的几种方式小结
2020/03/12 Python
Python实现寻找回文数字过程解析
2020/06/09 Python
关于PyCharm安装后修改路径名称使其可重新打开的问题
2020/10/20 Python
python中re模块知识点总结
2021/01/17 Python
html5中canvas学习笔记1-画板的尺寸与实际显示尺寸
2013/01/06 HTML / CSS
毕业生造价工程师求职信
2013/10/17 职场文书
安全教育月活动总结
2014/05/05 职场文书
2014年优秀班主任工作总结
2014/12/16 职场文书
2015毕业寄语大全
2015/02/26 职场文书
会议主持人开场白台词
2015/05/28 职场文书
2019关于垃圾分类处理的调查报告
2019/12/26 职场文书
vue-cli4.5.x快速搭建项目
2021/05/30 Vue.js
Python捕获、播放和保存摄像头视频并提高视频清晰度和对比度
2022/04/14 Python
vue 把二维或多维数组转一维数组
2022/04/24 Vue.js