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 判断浏览器类型 去全角、半角空格 自动关闭当前窗口
Apr 10 Javascript
JavaScript把数组作为堆栈使用的方法
Mar 20 Javascript
jQuery自动添加表单项的方法
Jul 13 Javascript
JS实现Fisheye效果动感放大菜单代码
Oct 21 Javascript
跟我学习javascript的arguments对象
Nov 16 Javascript
AngularJS Bootstrap详细介绍及实例代码
Jul 28 Javascript
使用Ajax生成的Excel文件并下载的实例
Nov 21 Javascript
javascript读取文本节点方法小结
Dec 15 Javascript
jQuery实现简单的计时器功能实例分析
Aug 29 jQuery
使用vue实现grid-layout功能实例代码
Jan 05 Javascript
vue下axios拦截器token刷新机制的实例代码
Jan 17 Javascript
AJAX XMLHttpRequest对象创建使用详解
Aug 20 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 Cookie的一个使用注意点
2008/11/08 PHP
PHPThumb PHP 图片缩略图库
2012/03/11 PHP
跟我学Laravel之安装Laravel
2014/10/15 PHP
php实现与python进行socket通信的方法示例
2017/08/30 PHP
关于实现代码语法标亮 dp.SyntaxHighlighter
2007/02/02 Javascript
javascript学习笔记(十四) window对象使用介绍
2012/06/20 Javascript
JavaScript控制两个列表框listbox左右交换数据的方法
2015/03/18 Javascript
setTimeout内不支持jquery的选择器的解决方案
2015/04/28 Javascript
javaScript中Math()函数注意事项
2015/06/18 Javascript
js实现选中复选框文字变色的方法
2015/08/14 Javascript
jQuery实现带渐显效果的人物多级关系图代码
2015/10/16 Javascript
JavaScript判断用户名和密码不能为空的实现代码
2016/05/16 Javascript
js document.getElementsByClassName的使用介绍与自定义函数
2016/11/25 Javascript
AngularJS之ionic 框架下实现 Localstorage本地存储
2017/04/22 Javascript
vue使用监听实现全选反选功能
2018/07/06 Javascript
vue-router之实现导航切换过渡动画效果
2019/10/31 Javascript
vue中使用极验验证码的方法(附demo)
2019/12/04 Javascript
[03:12]完美世界DOTA2联赛PWL DAY7集锦
2020/11/06 DOTA
Sanic框架基于类的视图用法示例
2018/07/18 Python
如何基于Python创建目录文件夹
2019/12/31 Python
Python实现大数据收集至excel的思路详解
2020/01/03 Python
flask 实现上传图片并缩放作为头像的例子
2020/01/09 Python
浅谈Python3实现两个矩形的交并比(IoU)
2020/01/18 Python
python 下载文件的多种方法汇总
2020/11/17 Python
python 批量下载bilibili视频的gui程序
2020/11/20 Python
如何查看python关键字
2021/01/17 Python
中国综合性网上购物商城:当当(网上卖书起家)
2016/11/16 全球购物
测控技术与仪器个人求职信范文
2013/12/30 职场文书
优秀大学生求职自荐信范文
2014/04/19 职场文书
2014乡镇干部对照检查材料思想汇报
2014/09/26 职场文书
离婚纠纷代理词
2015/05/23 职场文书
Nginx同一个域名配置多个项目的实现方法
2021/03/31 Servers
MySQL如何使用使用Xtrabackup进行备份和恢复
2021/06/21 MySQL
Java使用jmeter进行压力测试
2021/07/09 Java/Android
Java spring定时任务详解
2021/10/05 Java/Android
Linux下搭建SFTP服务器的命令详解
2022/06/25 Servers