postcss-pxtorem插件是如何把px转成rem的?

pxtorem

pxtorem 是一个 PostCSS插件,可以把CSS单位px转成rem。
例如,对下面的例子,假设根元素(html)的字体大小是16px,那么对所有的px换算规则就是:y = x/16 rem:

/** input */
h1 {
    margin: 0 0 20px;
    font-size: 32px;
    line-height: 1.2;
    letter-spacing: 1px;
}
/** output */
h1 {
    margin: 0 0 20px;
    font-size: 2rem;
    line-height: 1.2;
    letter-spacing: 0.0625rem;
}

分析

pxtorem是一个PostCSS插件,所以在写法上要遵循PostCSS的规则,利用PostCSS提供的钩子和API,可以在每个钩子上方便的获取到CSS转成AST之后对应的结果。如下,是该插件的代码结构:


image.png

主要是分析Once和Declaration这两个钩子。

Once钩子

Once钩子是在根节点上执行,对于每个css文件都会执行一次。

pxtorem插件这个阶段里面做了:

  1. 判断当前文件是否在exclude包含的路径内(exclude是用户使用时提供的配置);

  2. 获取根元素字体大小;

  3. 给变量pxReplace赋值(px转为rem的函数);


    image.png

createPxReplace比较简单,如下:


image.png

Declaration钩子

在所有声明节点上(color: black就是一个节点)调用和在节点或子级更改时再次调用。

  1. 当前文件是否不转化;

  2. 各种跳过转化的情况(不存在px 、属性不转化、选择器是否在需要被过滤的列表内);

  3. 把px转化成rem;


    image.png

那上面的decl.value = value 和 decl.cloneAfter({value: value})有什么区别呢?

decl.value是直接替换

  ul {                                ul {
    padding: 16px;     =>                padding: 1rem;
  }                                   }     

cloneAfter会在下方多加一行代码:

  ul {                                ul {
    padding: 16px;     =>              padding: 16px;
                                       padding: 1rem;
  }                                   }       

Q & A

为什么PX这种写法能被忽略转化:

官方问题提出最简单的忽略转化的方法是把px写成Px或者PX:
在代码里面,可以看到判断px是通过indexOf('px')来精确判断的:


image.png

结尾

PostCSS插件对大多数人来说是不需要自己去写的,现在有大量的PostCSS插件基本上覆盖了你需要的场景。但是我们可以了解下这个知识点,以后跳槽也有东西讲。

你可能感兴趣的:(postcss-pxtorem插件是如何把px转成rem的?)