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的一个图片hover的插件
Apr 24 Javascript
js固定DIV高度,超出部分自动添加滚动条的简单方法
Jul 10 Javascript
javascript中setInterval的用法
Jul 19 Javascript
jQuery Chart图表制作组件Highcharts用法详解
Jun 01 Javascript
基于jQuery实现简单人工智能聊天室
Feb 10 Javascript
微信小程序实现给循环列表添加点击样式实例
Apr 26 Javascript
webstorm+vue初始化项目的方法
Oct 18 Javascript
使用Angular material主题定义自己的组件库的配色体系
Sep 04 Javascript
JavaScript前端实现压缩图片功能
Mar 06 Javascript
vant-ui框架的一个bug(解决切换后onload不触发)
Nov 11 Javascript
javascript实现滚轮轮播图片
Dec 13 Javascript
JavaScript实现4位随机验证码的生成
Jan 28 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
比特率,大家看看这个就不用收音机音质去比MP3音质了
2021/03/01 无线电
php中filter函数验证、过滤用户输入的数据
2014/01/13 PHP
php中的观察者模式简单实例
2015/01/20 PHP
php上传图片并给图片打上透明水印的代码
2010/06/07 Javascript
jQuery的学习步骤
2011/02/23 Javascript
js jquery数组介绍
2012/07/15 Javascript
Ext JS 4官方文档之三 -- 类体系概述与实践
2012/12/16 Javascript
Jquery解析json数据详解
2013/12/26 Javascript
angular简介和其特点介绍
2015/01/29 Javascript
jQuery鼠标移动图片上实现放大效果
2017/06/25 jQuery
jQuery中 DOM节点操作方法大全
2017/10/12 jQuery
Vue 按键修饰符处理事件的方法
2018/05/04 Javascript
centos 上快速搭建ghost博客方法分享
2018/05/23 Javascript
angularJs中json数据转换与本地存储的实例
2018/10/08 Javascript
详解基于electron制作一个node压缩图片的桌面应用
2019/01/29 Javascript
小程序封装路由文件和路由方法(5种全解析)
2019/05/26 Javascript
layui动态绑定事件的方法
2019/09/20 Javascript
vue-cli3 引入 font-awesome的操作
2020/08/11 Javascript
解决await在forEach中不起作用的问题
2021/02/25 Javascript
python三元运算符实现方法
2013/12/17 Python
Python中使用bidict模块双向字典结构的奇技淫巧
2016/07/12 Python
对Python进行数据分析_关于Package的安装问题
2017/05/22 Python
Python3.6.0+opencv3.3.0人脸检测示例
2018/05/25 Python
Python单链表原理与实现方法详解
2020/02/22 Python
Python2及Python3如何实现兼容切换
2020/09/01 Python
利用CSS3实现平移动画效果示例代码
2016/10/12 HTML / CSS
HTML5使用DOM进行自定义控制示例代码
2013/06/08 HTML / CSS
科研先进个人典型材料
2014/01/31 职场文书
春季运动会广播稿大全
2014/02/19 职场文书
制药工程专业职业生涯规划范文
2014/03/10 职场文书
不拖欠农民工工资承诺书
2014/03/31 职场文书
3分钟英语演讲稿
2014/04/29 职场文书
股东大会通知
2015/04/24 职场文书
何玥事迹观后感
2015/06/16 职场文书
手把手教你用SpringBoot将文件打包成zip存放或导出
2021/06/11 Java/Android
vue3使用vuedraggable实现拖拽功能
2022/04/06 Vue.js