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高级拖动技术 setCapture,releaseCapture
Jul 31 Javascript
jq选项卡鼠标延迟的插件实例
May 13 Javascript
为指定的元素添加遮罩层的示例代码
Jan 15 Javascript
jQuery的图片滑块焦点图插件整理推荐
Dec 07 Javascript
jquery用ajax方式从后台获取json数据后如何将内容填充到下拉列表
Aug 26 Javascript
jQuery选择器基础入门教程
May 10 Javascript
jQuery图片加载失败替换默认图片方法汇总
Nov 29 jQuery
JavaScript中的高级函数
Jan 04 Javascript
JS严格模式知识点总结
Feb 27 Javascript
Vue.js点击切换按钮改变内容的实例讲解
Aug 22 Javascript
微信实现自动跳转到用其他浏览器打开指定APP下载
Feb 15 Javascript
vue elementUI批量上传文件
Apr 26 Vue.js
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
重量级动漫纷纷停播!唯独OVERLORD第四季正在英魂之刃继续更新
2020/05/06 日漫
PHP高手需要要掌握的知识点
2014/08/21 PHP
PHP将MySQL的查询结果转换为数组并用where拼接的示例
2016/05/13 PHP
ThinkPHP 3使用OSS的方法
2018/07/19 PHP
一直复略了的一个问题,关于表单重复提交
2007/02/15 Javascript
jQuery 中使用JSON的实现代码
2011/12/01 Javascript
浅析document.ready和window.onload的区别讲解
2013/12/18 Javascript
js实现的类似于asp数据字典的数据类型代码实例
2014/09/03 Javascript
PHP中CURL的几个经典应用实例
2015/01/23 Javascript
jQuery实现带滚动导航效果的全屏滚动相册实例
2015/06/19 Javascript
jquery实现可点击伸缩与展开的菜单效果代码
2015/08/31 Javascript
举例讲解JavaScript substring()的使用方法
2015/11/09 Javascript
动态创建按钮的JavaScript代码
2016/01/29 Javascript
AngularJS使用ng-repeat和ng-if实现数据的删选显示效果示例【适用于表单数据的显示】
2016/12/13 Javascript
JavaScript实现的数字与字符串转换功能示例
2017/08/23 Javascript
element-ui table span-method(行合并)的实现代码
2018/12/20 Javascript
解决Vue打包后访问图片/图标不显示的问题
2019/07/25 Javascript
微信小程序canvas绘制圆角base64图片的实现
2019/08/18 Javascript
layui实现显示数据表格、搜索和修改功能示例
2020/06/03 Javascript
[02:41]DOTA2英雄基础教程 谜团
2013/12/10 DOTA
python高并发异步服务器核心库forkcore使用方法
2013/11/26 Python
在Python的Flask框架下使用sqlalchemy库的简单教程
2015/04/09 Python
Python利用itchat对微信中好友数据实现简单分析的方法
2017/11/21 Python
Python读取图片为16进制表示简单代码
2018/01/19 Python
Python3爬虫全国地址信息
2019/01/05 Python
在python里面运用多继承方法详解
2019/07/01 Python
美国网上书店:Barnes & Noble
2018/08/15 全球购物
美国购买舞会礼服网站:Couture Candy
2019/12/29 全球购物
老师自我鉴定范文
2013/12/25 职场文书
教师旷工检讨书
2014/01/18 职场文书
消防验收申请报告
2015/05/15 职场文书
党支部培养考察意见
2015/06/02 职场文书
心理学培训心得体会
2016/01/22 职场文书
2019消防宣传标语!
2019/07/10 职场文书
Python通过loop.run_in_executor执行同步代码 同步变为异步
2022/04/11 Python
MySQL控制流函数(-if ,elseif,else,case...when)
2022/07/07 MySQL