What: 什么是postcss
PostCSS 是一个允许使用 JS 插件转换样式的工具。 这些插件可以检查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 编译尚未被浏览器广泛支持的先进的 CSS 语法,内联图片,以及其它很多优秀的功能。
PostCSS 在工业界被广泛地应用,其中不乏很多有名的行业领导者,如:维基百科,Twitter,阿里巴巴, JetBrains。PostCSS 的 Autoprefixer 插件是最流行的 CSS 处理工具之一。
更多资料请查阅github项目: postcss
Why: 为什么要使用它
解决问题: 如何实现数据驱动样式?
在研究一个项目, 它需要实现一个动态样式的更改, 比如点击某元素让他的背景颜色变为#f00
.
要实现这个我暂时想到2个方法:
1. 内联样式
如 :style="{"background":"#f00"}"
我们需要定义一个对象里面存放{"background":"xxx";"padding":"xpx"}
, 然后给dom的style属性绑定上这个对象. 当用户点击这个组件的时候, 将对象值改变即可.
这样是可以实现, 但思考以下问题:
- 如何模拟出
:hover {background:#fff}
, 也就是怎么模拟伪类? - 当属性很多的时候, 会不会影响到vue的渲染速度?
- 全部内联是不是有点不太优雅?
可见这不是最佳方法
2. 动态生成<style>标签
我们可以动态生成一段<style>标签添加到html里, 这样就可以很方便的实现:hover
效果, 也不会影响到渲染效率.
看似很完美, 我们就使用这个方法.
那么要解决的问题就是这么从一个js对象{"background":"xxx";"padding":"xpx"}
转换成css代码? 对于简单的对象我们可以手拼, 但对于一个复杂的, 支持嵌套的结构我们能确定手动能拼好吗? 按照不重复造轮子原则, 我需要一个已经写好了的处理css的利器, 于是我找到了postcss
.
How: 如何使用postcss
首先明确我们的目的: 将js对象解析成css
postcss说它有200多个插件, 一眼扫去不难发现一个postcss-js
的插件:
postcss-js
允许你在 JS 里编写样式,或者转换成 React 的内联样式/Radium/JSS。
这个插件正是我们所需要的啊.
查阅文档发现使用方法如下:
Compile CSS-in-JS to CSS
let style = { top: 10, '&:hover': { top: 5 } }; postcss().process(style, { parser: postcssJs }).then( (result) => { result.css //=> top: 10px; // &:hover { top: 5px; } })
这货还支持嵌套css? 岂不是更爽. 笑出声
各种尝试之后我封装了如下方法
// postcss-js.js
// 请先npm install 相关包
import postcss from 'postcss' // postcss
import postcssJs from 'postcss-js' // css
import autoprefixer from 'autoprefixer' // 自动前缀
import nested from 'postcss-nested' // 嵌套语法
import variables from 'postcss-css-variables' // 支持变量 如:root{--a:#333}
function processCssJs(cssJs) {
return postcss([autoprefixer, nested, variables]).process(
cssJs, {parser: postcssJs}).css
}
export default processCssJs
ps: 200个插件总有有用的, 多翻翻.
我们来看看这个方法可以干什么事?
input:
{
":root"{
--c:#fff
}
"#id1": {
"backgrounColor": var(--c),
"&:hover": {
"backgrounColor": "#eee"
}
}
}
output:
#id1{
backgroun-color:#fff
}
#id1:hover{
backgroun-color:#eee
}
简直完美
当然我只是给定一个简单的结构举例, 实际使用中, 我们可以在js对象中写像less
,sass
那样复杂的嵌套,
你可以试一试.
题外话
一般来说, 一个组件会有一个js对象来表述样式. 那么针对这个js对象就要生成一个<style>标签.
一个组件一段<style>是不是有不太优雅? 我们想把style统一放在一个地方. 有以下两个方案。
方案1: vuex, 每个组件emit自己的cssjs, 然后用统一一个组件去渲染这些cssjs.
方案2: 做一个vue的plugin, 给Vue的原型链上添加一些方法以实现每个组件都可以emit自己的cssjs, 然后用统一一个组件去渲染这些cssjs.
具体的自由发挥吧.
网友评论