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 相关文章推荐
JavaScript中的Window窗口对象
Jan 16 Javascript
基于jQuery的一个扩展form序列化到json对象
Dec 09 Javascript
超轻量级的基于jquery的三级展开列表
Apr 26 Javascript
jQuery中setTimeout的几种使用方法小结
Apr 07 Javascript
JQuery Mobile实现导航栏和页脚
Mar 09 Javascript
JavaScript的字符串方法汇总
Jul 31 Javascript
jQuery实现动态添加、删除按钮及input输入框的方法
Apr 27 jQuery
jquery实现图片上传前本地预览
Apr 28 jQuery
JavaScript实现简单音乐播放器
Apr 17 Javascript
element-ui组件table实现自定义筛选功能的示例代码
Mar 15 Javascript
layui关闭弹窗后刷新主页面和当前更改项的例子
Sep 06 Javascript
解决layui弹出层layer的area过大被遮挡的问题
Sep 21 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中使用数组实现堆栈数据结构的代码
2012/02/05 PHP
php遍历目录方法小结
2015/03/10 PHP
如何在centos8自定义目录安装php7.3
2019/11/28 PHP
详解no input file specified 三种解决方法
2019/11/29 PHP
Jquery+JSon 无刷新分页实现代码
2010/04/01 Javascript
关于jquery append() html时的小问题的解决方法
2010/12/16 Javascript
元素的内联事件处理函数的特殊作用域在各浏览器中存在差异
2011/01/12 Javascript
js定时器的使用(实例讲解)
2014/01/06 Javascript
浅析js预加载/延迟加载
2014/09/25 Javascript
JavaScript中使用document.write向页面输出内容实例
2014/10/16 Javascript
bootstrap学习笔记之初识bootstrap
2016/06/21 Javascript
Javascript 实现简单计算器实例代码
2016/10/23 Javascript
Bootstrap CSS布局之按钮
2016/12/17 Javascript
JS正则匹配中文的方法示例
2017/01/06 Javascript
jquery表单验证实例仿Toast提示效果
2017/03/03 Javascript
vue.js实现插入数值与表达式的方法分析
2018/07/06 Javascript
详解Element 指令clickoutside源码分析
2019/02/15 Javascript
使用python实现扫描端口示例
2014/03/29 Python
Python中的os.path路径模块中的操作方法总结
2016/07/07 Python
python入门教程之识别验证码
2017/03/04 Python
详解Pytorch 使用Pytorch拟合多项式(多项式回归)
2018/05/24 Python
解决django服务器重启端口被占用的问题
2019/07/26 Python
Python 远程开关机的方法
2020/11/18 Python
如何在vscode中安装python库的方法步骤
2021/01/06 Python
使用bandit对目标python代码进行安全函数扫描的案例分析
2021/01/27 Python
应届电子商务毕业自荐书范文
2014/02/11 职场文书
制药工程专业职业生涯规划范文
2014/03/10 职场文书
农行心得体会
2014/09/02 职场文书
党的群众路线教育实践活动心得体会(医院)
2014/11/03 职场文书
公司门卫岗位职责
2015/04/13 职场文书
人口与计划生育责任书
2015/05/09 职场文书
陪护人员误工证明
2015/06/24 职场文书
争做文明公民倡议书
2019/06/24 职场文书
Python WSGI 规范简介
2021/04/11 Python
小程序实现文字循环滚动动画
2021/06/14 Javascript
Redisson实现Redis分布式锁的几种方式
2021/08/07 Redis