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 window.event对象详尽解析
Feb 17 Javascript
cloudgamer出品ImageZoom 图片放大效果
Apr 01 Javascript
JQuery跨Iframe选择实现代码
Aug 19 Javascript
Extjs表单常见验证小结
Mar 07 Javascript
node.js中的console.time方法使用说明
Dec 09 Javascript
javascript中不易分清的slice,splice和split三个函数
Mar 29 Javascript
微信小程序开发之从相册获取图片 使用相机拍照 本地图片上传
Apr 18 Javascript
jquery实现下拉菜单的手风琴效果
Jul 23 jQuery
浅谈js获取ModelAndView值的问题
Mar 28 Javascript
express.js中间件说明详解
Mar 19 Javascript
原生js实现轮播图特效
May 04 Javascript
解决vue net :ERR_CONNECTION_REFUSED报错问题
Aug 13 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网站备份程序代码分享
2011/06/10 PHP
Php output buffering缓存及程序缓存深入解析
2013/07/15 PHP
linux系统下php安装mbstring扩展的二种方法
2014/01/20 PHP
php及codeigniter使用session-cookie的方法(详解)
2017/04/06 PHP
PHP CodeIgniter分页实例及多条件查询解决方案(推荐)
2017/05/20 PHP
DOM相关内容速查手册
2007/02/07 Javascript
javascript下数值型比较难点说明
2010/06/07 Javascript
prettify 代码高亮着色器google出品
2010/12/28 Javascript
浅析jQuery1.8的几个小变化
2013/12/10 Javascript
javascript事件冒泡详解和捕获、阻止方法
2014/04/12 Javascript
ECMAScript5(ES5)中bind方法使用小结
2015/05/07 Javascript
javascript中一些util方法汇总
2015/06/10 Javascript
JS 获取HTML标签内的子节点的方法
2016/09/21 Javascript
Node.js 数据加密传输浅析
2016/11/16 Javascript
Bootstrap + AngularJS 实现简单的数据过滤字符查找功能
2017/07/27 Javascript
微信小程序实现图片压缩
2019/12/03 Javascript
js 动态校验开始结束时间的实现代码
2020/05/25 Javascript
Vue-Ant Design Vue-普通及自定义校验实例
2020/10/24 Javascript
python实现在控制台输入密码不显示的方法
2015/07/02 Python
python魔法方法-属性转换和类的表示详解
2016/07/22 Python
Puppeteer使用示例详解
2019/06/20 Python
打包python 加icon 去掉cmd黑窗口方法
2019/06/24 Python
python傅里叶变换FFT绘制频谱图
2019/07/19 Python
postman和python mock测试过程图解
2020/02/22 Python
python实现简单的五子棋游戏
2020/09/01 Python
详解python的super()的作用和原理
2020/10/29 Python
python中xlutils库用法浅析
2020/12/29 Python
Old Navy加拿大官网:美式休闲服饰品牌
2017/09/26 全球购物
IdealFit官方网站:女性蛋白质、补充剂和运动服装
2019/03/24 全球购物
荷兰最大的鞋子、服装和运动折扣店:Bristol
2021/01/07 全球购物
采购文员岗位职责
2013/11/20 职场文书
祖国在我心中演讲稿450字
2014/09/05 职场文书
党员领导干部民主生活会批评与自我批评发言
2014/09/28 职场文书
中学生自我评价2015
2015/03/03 职场文书
2015年清剿火患专项行动工作总结
2015/07/27 职场文书
go web 预防跨站脚本的实现方式
2021/06/11 Golang