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实现随机返回数组的一个元素
Aug 13 Javascript
合并table相同单元格的jquery插件分享(很精简)
Jun 20 Javascript
圣诞节Merry Christmas给博客添加浪漫的下雪效果基于jquery实现
Dec 27 Javascript
JavaScript使用HTML5的window.postMessage实现跨域通信例子
Apr 11 Javascript
jQuery点击弹出层弹出模态框点击模态框消失代码分享
Jan 21 Javascript
jquery pagination分页插件使用详解(后台struts2)
Jan 22 Javascript
xmlplus组件设计系列之按钮(2)
Apr 26 Javascript
详解小程序开发经验:多页面数据同步
May 18 Javascript
微信小程序 搜索框组件代码实例
Sep 06 Javascript
js canvas实现星空连线背景特效
Nov 01 Javascript
JavaScript如何实现图片处理与合成
May 29 Javascript
ant-design-vue 时间选择器赋值默认时间的操作
Oct 27 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
Terran兵种对照表
2020/03/14 星际争霸
在命令行下运行PHP脚本[带参数]的方法
2010/01/22 PHP
PHP面向对象程序设计之接口用法
2014/08/20 PHP
php选择排序法实现数组排序实例分析
2015/02/16 PHP
php基于mcrypt_encrypt和mcrypt_decrypt实现字符串加密解密的方法
2016/07/12 PHP
微信公众号开发之获取位置信息php代码
2018/06/13 PHP
解决Laravel 使用insert插入数据,字段created_at为0000的问题
2019/10/11 PHP
Laravel6.2中用于用户登录的新密码确认流程详解
2019/10/16 PHP
newxtree.js代码
2007/03/13 Javascript
向fckeditor编辑器插入指定代码的方法
2007/05/25 Javascript
关于juqery radio写法的兼容性问题(新老版本jquery)
2010/06/14 Javascript
高效的表格行背景隔行变色及选定高亮的JS代码
2010/12/04 Javascript
juqery 学习之六 CSS--css、位置、宽高
2011/02/11 Javascript
客户端js性能优化小技巧整理
2013/11/05 Javascript
window.location 对象所包含的属性
2014/10/10 Javascript
轻松学习jQuery插件EasyUI EasyUI创建RSS Feed阅读器
2015/11/30 Javascript
Bootstrap每天必学之附加导航(Affix)插件
2016/04/25 Javascript
网站发布后Bootstrap框架引用woff字体无法正常显示的解决方法
2016/11/24 Javascript
JavaScript字符串_动力节点Java学院整理
2017/06/27 Javascript
Node.js中流(stream)的使用方法示例
2017/07/16 Javascript
Vue.js递归组件实现组织架构树和选人功能案例分析
2019/07/03 Javascript
vue实现输入框的模糊查询的示例代码(节流函数的应用场景)
2019/09/01 Javascript
vue实现扫码功能
2020/01/17 Javascript
[00:58]PWL开团时刻DAY5——十人开雾0换5
2020/11/04 DOTA
[38:54]完美世界DOTA2联赛PWL S2 Rebirth vs LBZS 第一场 11.28
2020/12/01 DOTA
python中的内置函数max()和min()及mas()函数的高级用法
2018/03/29 Python
python提取图像的名字*.jpg到txt文本的方法
2018/05/10 Python
我就是这样学习Python中的列表
2019/06/02 Python
详解Python中的正斜杠与反斜杠
2019/08/09 Python
pytorch 准备、训练和测试自己的图片数据的方法
2020/01/10 Python
网络安全方面的面试题
2016/01/07 面试题
保险公司开门红口号
2014/06/21 职场文书
巾帼标兵事迹材料
2014/12/26 职场文书
体育部部长竞选稿
2015/11/21 职场文书
MySQL如何使备份得数据保持一致
2022/05/02 MySQL
Redis特殊数据类型bitmap位图
2022/06/01 Redis