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的图片大小自动适应实现代码
Nov 17 Javascript
javascript算法学习(直接插入排序)
Apr 12 Javascript
当jQuery遭遇CoffeeScript的时候 使用分享
Sep 17 Javascript
Javascript new Date().valueOf()的作用与时间戳由来详解
Apr 24 Javascript
jQuery输入城市查看地图使用介绍
May 08 Javascript
javascript实现div的显示和隐藏的小例子
Jun 25 Javascript
JS的千分位算法实现思路
Jul 31 Javascript
javascript随机显示背景图片的方法
Jun 18 Javascript
jQuery 1.9.1源码分析系列(十三)之位置大小操作
Dec 02 Javascript
工作中常用的js、jquery自定义扩展函数代码片段汇总
Dec 22 Javascript
微信小程序图表插件(wx-charts)实例代码
Jan 17 Javascript
jQuery 筛选器简单操作示例
Oct 02 jQuery
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
Smarty+QUICKFORM小小演示
2007/02/25 PHP
浅谈PHP与C#的值类型指向区别的详解
2013/05/21 PHP
php实现微信公众平台账号自定义菜单类
2014/12/02 PHP
PHP JSON格式的中文显示问题解决方法
2015/04/09 PHP
PHP中的数组处理函数实例总结
2016/01/09 PHP
一句话JavaScript表单验证代码
2009/08/02 Javascript
JavaScript 一道字符串分解的题目
2011/08/03 Javascript
js隐藏与显示回到顶部按钮及window.onscroll事件应用
2013/01/25 Javascript
jquery数据验证插件(自制,简单,练手)实例代码
2013/10/24 Javascript
js用typeof方法判断undefined类型
2014/07/15 Javascript
学习Bootstrap组件之下拉菜单
2015/07/28 Javascript
Bootstrap复选框和单选按钮美化插件(推荐)
2016/11/23 Javascript
JavaScript中的this陷阱的最全收集并整理(没有之一)
2017/02/21 Javascript
jQuery获取table下某一行某一列的值实现代码
2017/04/07 jQuery
JS原生带小白点轮播图实例讲解
2017/07/22 Javascript
VUE中的无限循环代码解析
2017/09/22 Javascript
VueJS事件处理器v-on的使用方法
2017/09/27 Javascript
深入koa-bodyparser原理解析
2019/01/16 Javascript
javascript验证form表单数据的案例详解
2019/03/25 Javascript
[00:12]DAC2018 Miracle-站上中单舞台,他能否再写奇迹?
2018/04/06 DOTA
python如何实现excel数据添加到mongodb
2015/07/30 Python
使用XML库的方式,实现RPC通信的方法(推荐)
2017/06/14 Python
Python爬虫抓取代理IP并检验可用性的实例
2018/05/07 Python
Pyqt5 实现跳转界面并关闭当前界面的方法
2019/06/19 Python
python创建n行m列数组示例
2019/12/02 Python
python实现登录与注册系统
2020/11/30 Python
HTML5实现动画效果的方式汇总
2016/02/29 HTML / CSS
Hanky Panky官方网站:内衣和睡衣
2019/07/25 全球购物
新媒传信软件测试面试题
2013/02/24 面试题
2014年开学第一课活动方案
2014/03/06 职场文书
婚前协议书标准版
2014/10/19 职场文书
2014年安全工作总结范文
2014/11/13 职场文书
大学生自荐信怎么写
2015/03/26 职场文书
农村党支部承诺书
2015/04/30 职场文书
2019垃圾分类宣传口号汇总
2019/08/16 职场文书
利用Java连接Hadoop进行编程
2022/06/28 Java/Android