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 相关文章推荐
JQUERY THICKBOX弹出层插件
Aug 30 Javascript
用jquery ajax获取网站Alexa排名的代码
Dec 12 Javascript
js 绑定带参数的事件以及手动触发事件
Apr 27 Javascript
javascript 伪数组实现方法
Oct 11 Javascript
Jquery公告滚动+AJAX后台得到数据
Apr 14 Javascript
Javascript中call的两种用法实例
Dec 13 Javascript
jQuery之选项卡的简单实现
Feb 28 Javascript
AngularJS表单验证中级篇(3)
Sep 28 Javascript
深入理解JavaScript中的尾调用(Tail Call)
Feb 07 Javascript
了解VUE的render函数的使用
Jun 08 Javascript
JavaScript面向对象精要(下部)
Sep 12 Javascript
基于vue.js无缝滚动效果
Jan 25 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中的时间处理
2006/10/09 PHP
php 小乘法表实现代码
2009/07/16 PHP
CI框架中集成CKEditor编辑器的教程
2014/06/09 PHP
php读取csv文件并输出的方法
2015/03/14 PHP
PHP中使用jQuery+Ajax实现分页查询多功能操作(示例讲解)
2017/09/17 PHP
讲两件事:1.this指针的用法小探. 2.ie的attachEvent和firefox的addEventListener在事件处理上的区别
2007/04/12 Javascript
Jquery乱码的一次解决过程 图解教程
2010/02/20 Javascript
Jquery获取复选框被选中值的简单方法
2013/07/04 Javascript
基于JavaScript 下namespace 功能的简单分析
2013/07/05 Javascript
浅析jQuery中调用ajax方法时在不同浏览器中遇到的问题
2014/06/11 Javascript
基于Javascript实现文件实时加载进度的方法
2016/10/12 Javascript
AngularJS实现ajax请求的方法
2016/11/22 Javascript
Bootstrap下拉菜单样式
2017/02/07 Javascript
vue 通过下拉框组件学习vue中的父子通讯
2017/12/19 Javascript
vue使用echarts图表的详细方法
2018/10/22 Javascript
js字符串处理之绝妙的代码
2019/04/05 Javascript
微信小程序实现批量倒计时功能
2020/11/01 Javascript
基于layui框架响应式布局的一些使用详解
2019/09/16 Javascript
flexible.js实现移动端rem适配方案
2020/04/07 Javascript
详解JavaScript中new操作符的解析和实现
2020/09/04 Javascript
Vue实现开关按钮拖拽效果
2020/09/22 Javascript
[01:31]完美与DOTA2历程
2014/07/31 DOTA
[43:26]完美世界DOTA2联赛PWL S2 Forest vs Rebirth 第二场 11.20
2020/11/23 DOTA
python清除字符串里非字母字符的方法
2015/07/02 Python
使用python3+xlrd解析Excel的实例
2018/05/04 Python
基于python批量处理dat文件及科学计算方法详解
2018/05/08 Python
对python 多个分隔符split 的实例详解
2018/12/20 Python
Python之循环结构
2019/01/15 Python
利用ctypes获取numpy数组的指针方法
2019/02/12 Python
Python 硬币兑换问题
2019/07/29 Python
python连接打印机实现打印文档、图片、pdf文件等功能
2020/02/07 Python
KIKO MILANO英国官网:意大利知名化妆品和护肤品品牌
2017/09/25 全球购物
ShellScript面试题一则-ShellScript编程
2014/03/05 面试题
2014年大堂经理工作总结
2014/11/21 职场文书
DjangoRestFramework 使用 simpleJWT 登陆认证完整记录
2021/06/22 Python
Vue h函数的使用详解
2022/02/18 Vue.js