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 相关文章推荐
WordPress JQuery处理沙发头像
Jun 22 Javascript
javascript中call apply 的应用场景
Apr 16 Javascript
Jquery1.9.1源码分析系列(十五)动画处理之外篇
Dec 04 Javascript
深入浅析Extjs中store分组功能的使用方法
Apr 20 Javascript
省市联动效果的简单实现代码(推荐)
Jun 06 Javascript
AngularJS入门教程之数据绑定原理详解
Nov 02 Javascript
Mongoose经常返回e11000 error的原因分析
Mar 29 Javascript
关于vue的语法规则检测报错问题的解决
May 21 Javascript
vue.js通过路由实现经典的三栏布局实例代码
Jul 08 Javascript
JS实现动态生成html table表格的方法分析
Jul 11 Javascript
VUE解决 v-html不能触发点击事件的问题
Oct 28 Javascript
使用Ajax实现无刷新上传文件
Apr 12 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
PHP+DBM的同学录程序(4)
2006/10/09 PHP
php class中self,parent,this的区别以及实例介绍
2013/04/24 PHP
Laravel框架实现修改登录和注册接口数据返回格式的方法
2018/08/17 PHP
解决在laravel中auth建立时候遇到的问题
2019/10/15 PHP
Prototype使用指南之selector.js说明
2008/10/26 Javascript
js tab效果的实现代码
2009/12/26 Javascript
jquery json 实例代码
2010/12/02 Javascript
Javascript公共脚本库系列(一): 弹出层脚本
2011/02/24 Javascript
使用Jquery实现点击文字后变成文本框且可修改
2013/09/21 Javascript
js调用css属性写法
2013/09/21 Javascript
如何书写高质量jQuery代码(使用jquery性能问题)
2014/06/30 Javascript
js中的eval()函数把含有转义字符的字符串转换成Object对象的方法
2016/12/02 Javascript
JS简单获取日期相差天数的方法
2017/04/24 Javascript
js 原生判断内容区域是否滚动到底部的实例代码
2017/11/15 Javascript
Javascript防止图片拉伸的自适应处理方法
2017/12/26 Javascript
示例vue 的keep-alive缓存功能的实现
2018/12/13 Javascript
vue项目前端埋点的实现
2019/03/06 Javascript
Node.js+ELK日志规范的实现
2019/05/23 Javascript
LayUI动态设置checkbox不显示的解决方法
2019/09/02 Javascript
Vue+Element-U实现分页显示效果
2020/11/15 Javascript
一个检测OpenSSL心脏出血漏洞的Python脚本分享
2014/04/10 Python
Python做文本按行去重的实现方法
2016/10/19 Python
对pandas中Series的map函数详解
2018/07/25 Python
python实现任意位置文件分割的实例
2018/12/14 Python
pytorch 获取层权重,对特定层注入hook, 提取中间层输出的方法
2019/08/17 Python
使用python实现希尔、计数、基数基础排序的代码
2019/12/25 Python
Python中import导入不同目录的模块方法详解
2020/02/18 Python
opencv 图像轮廓的实现示例
2020/07/08 Python
css3学习心得分享
2013/08/19 HTML / CSS
Html5 Canvas 实现一个“刮刮乐”游戏
2019/09/05 HTML / CSS
html+js 实现markdown编辑器效果
2019/10/23 HTML / CSS
Alba Moda瑞士网上商店:独家意大利时尚女装销售
2016/11/28 全球购物
计算机维护专业推荐信
2014/02/27 职场文书
高中学生会竞选演讲稿
2014/08/25 职场文书
公务员考察材料范文
2014/12/23 职场文书
医院党建工作总结2015
2015/05/26 职场文书