大家好,我是卡颂。
不知道平时在项目里你怎么处理CSS
呢?
我们知道,由于原生CSS
存在一些问题,比如:
- 复用时容易样式冲突
- 没有作用域、没有模块化
- 没有编程能力
社区涌现出很多解决方案,比如:
- 命名规范(比如
BEM
规范) - 模块规范(CSS Modules)
CSS
预处理器(比如Less
)CSS In JS
CSS
框架(Tailwind CSS
)
......
如果我们按以下三个维度评判这些方案:
- 上手难度:与原生
CSS
越接近,越好上手 - 灵活性:拥有越强编程能力,越灵活
- 能力:能解决多少原生
CSS
的问题
会发现每个方案都有自己的优势与短板。
比如:
CSS In JS
方案用JS
写CSS
,拥有极高灵活性,但加大了上手难度Less
(CSS
预处理器)可以看作CSS
的超集,上手难度低、有一定编程能力,但是CSS
自身的问题他也存在
业界常见做法是:同时使用BEM
规范(解决命名冲突问题)+ CSS
预处理器。
进击的Vue CSS解决方案
我们用这三个维度分析下Vue
的SFC
(Single-File-Component,单文件组件):
<template>
<p>xxx</p>
</template>
<script>
// ...
</script>
<style scoped>
p {
color: #0f0;
}
</style>
- 上手难度:样式在
<style>
标签内书写,与原生CSS
别无二致,上手简单,符合直觉 - 能力:
scoped
标识提供了模块化能力 - 灵活性:可以使用各种预处理器,有一定灵活性
可以看到,Vue SFC
采用的是一种各方面没有明显短板,局部很突出(上手难度低)的CSS
方案。
随着Vue
3.2发布,Vue SFC
中的CSS
属性获得了响应式更新能力,使其灵活性大大提升。
响应式CSS属性
对于如下Vue SFC
:
<template>
<div class="text">hello</div>
</template>
<script>
export default {
data() {
return {
color: 'red'
}
}
}
</script>
<style>
.text {
color: v-bind(color);
}
</style>
<script>
标签内定义了状态color = 'red'
.text
使用v-bind
为color
属性绑定该状态。效果如下:
为了验证响应式更新能力, 为div
增加点击事件:
<div class="text" @click="color= color === 'red' ? 'green' : 'red'">hello</div>
点击后会让color
状态在red
与green
间切换。可以看到,页面样式也会同步变化:
Demo地址
不仅是color
,你可以为任何CSS
属性绑定状态。
那么这个特性是如何实现的呢?
实现原理
每个使用v-bind
绑定到CSS
属性的状态对应一个CSS
变量,该CSS
变量会作为style
属性赋值给组件最外层DOM
。
在我们的例子中:
.text {
color: v-bind(color);
}
其中v-bind(color)
会成为CSS
变量:
并作为style
属性赋值给div
:
.text
经过编译会使用该CSS
变量:
.text {
// 编译前
/* color: v-bind(color); */
// 编译后
color: var(--469af010-color);
}
当颜色变化后,CSS
变量的值随之变化:
所以,要使用这个特性需要目标浏览器支持CSS
变量。
Vue3
放弃IE
这可是说到做到的。
总结
Vue
官方称该特性为State-Driven Dynamic CSS。
经过这波操作,Vue SFC
的CSS
灵活性有了很大提高。
并且,有了v-bind
这个开头,相信未来会出现更多与响应式更新挂钩的自定义CSS指令。
之前的自定义指令都是运行时的,以后的指令可能会是基于AST
的编译时了。这种转变,你接受吗?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。