Vue 3.0.3 : 新增CSS变量传递以及最新的Ref提案
前言
在 Vue 3.03 版本中,Ref 语法糖已经实现,即使反对的人再多,尤雨溪也坚信这一语法糖会像 TypeScript 一样,用之前都觉得不好,用过之后说真香
。
所以不顾大家的反对,毅然决然的实现了这一需求,首先我们先来简单的回顾一下这个语法糖是干什么的:
Ref 语法糖
在之前,我们想要定义一个基本数据类型的响应式变量需要写成这样:
import { ref } from 'vue
const a = ref(0)
当使用时要写成这样:
a.value = a.value + 10
// 或 a.value += 10
这个value
属性就很烦人了,因为咱们定义了一个数字0
,给它取了个名字叫a
,虽然咱们并不是写成了这样:
const a = 0
但是在好多人的心目中,这个a
就像上面这行代码一样,觉得它应该是基础类型,一方面不符合直觉,经常会忘记写.value
。另一方面写起来也很麻烦,而且有时候需要写.value
,有时候又不需要,比如用在<template>
标签中时就不需要写.value
,或者把ref
赋值给reactive
对象时:
import { ref, reactive } from 'vue'
const obj = reactive({
a: ref(0)
})
// 这里不需要写成obj.a.value
console.log(obj.a)
这无疑为我们增加了许多的心智负担,尤雨溪希望通过编译来实现像使用基础类型一样使用ref
,写法如下:
// 声明一个变量(这个变量将会被编译成一个ref)
ref: count = 1
function inc() {
// 该变量可以像普通变量那样使用
count++
}
// 想要获取到原本的变量的话需要在变量前面加一个????符号
console.log($count.value)
Vue 3.0.3 CHANGELOG
通过 GitHub 中尤雨溪的 CHANGELOG 我们可以得知:
前半段写的修复的 Bug???? 先暂且不提,咱们只看新的实验性特性有哪些:
- compileScript inline render function mode
- new script setup implementation
- new SFC css varaible injection implementation
- support kebab-case components in <script setup> sfc template
- explicit expose API
这里面重点是第二条、第三条以及最后一条: - 实现了新的
<script setup>
- 实现了新的单文件组件注入 CSS 变量
- 控制导出的
expose
API
那么新的<script setup>
就包含了这个 Ref 语法糖。
CSS 变量注入
那么这个CSS变量注入
又是个什么鬼呢?
其实有篇文章已经把这个特性说的相当详细了:
总结起来就是:
- 以前在 JS 中的变量不能直接和 CSS 变量产生联系
- 现在可以在
<style>
标签中将 JS 变量与 CSS 变量进行关联 - 同时还具有响应性,比如改变了 JS 中 this.xxx 的值,同名的 CSS 变量也会随之改变,视图随之进行更新:
<template>
<h1>Vue</h1>
</template>
<script>
export default {
data () {
return {
opacity: 0
}
},
mounted () {
setInterval(_ => {
this.opacity >= 1 && (this.opacity = 0)
this.opacity += 0.2
}, 300)
}
}
</script>
<style vars="{ opacity }">
h1 {
color: rgb(65, 184, 131);
opacity: var(--opacity);
}
</style>
运行结果:
可以看到有了这一特性,我们只需要改变同名的 JS 变量即可,这会让我们的项目更加的灵活,比如根据用户输入的合法颜色值来进行动态换肤等功能。
但这次更新改变了写法,在<style>
标签中不需要再写vars="{ xxx }"
了,在 CSS 代码中也不需要再写原生的 CSS 变量引用了(var(--xxx)
),取而代之的是v-bind()
这个函数,注意 ⚠️ 这个函数虽然跟 JS 里的v-bind
很像,但只能用在 CSS 中,写法如下:
<template>
<h1> shit! </h1>
</template>
<script>
export default {
data () {
return {
color: 'yellow'
}
}
}
</script>
<style>
h1 {
color: v-bind(color)
}
</style>
如果是 JS 变量是xxx.xxx
这种形式的话,比如这样:
export default {
data () {
return {
font: {
weight: 100
}
}
}
}
那么 CSS 不能直接写成这样:
h1 {
font-weight: v-bind(font.weight)
}
而是需要用一对引号扩起来,类似于字符串的那种形式:
h1 {
font-weight: v-bind('font.weight')
}
expose API
那么这又是个什么鬼呢?
在 Vue 2 时期我们是通过 Options API 来写代码的,也就是说需要导出一个对象,对象的键无非就是那些耳熟能详的:
export default {
data () {},
mounted () {},
computed: {},
methods: {},
// 省略若干 Options ...
}
而现在新加了一个 expose:
export default {
data () {},
mounted () {},
computed: {},
methods: {},
// 省略若干 Options ...
expose: []
}
这玩意是干嘛的呢?首先它的用法和 props 的数组形式差不多:
export default {
data () {
return {
x: 1,
y: 2
}
},
expose: [ 'x' ]
}
这样的话在父组件中用 ref 获取子组件实例时,子组件身上只有x
这个变量,y
是获取不到的!
而在 Composition API 中的用法是这样的:
export default defineComponent((_, { expose }) => {
expose({
x: ref(1)
})
return {
x: ref(2),
y: ref(3)
}
}
})
看!咱们这里有两个x
,你们猜哪个x
会被导出?
答案是如果有两个导出的变量的话,以 expose
导出的为准。
那么 Composition API 和 Options API 混合用法会是什么样的呢:
expotr default defineComponent({
expose: ['x'],
data () {
return {
x: 1
}
},
setup (_, { expose }) {
expose({
y: ref(2)
})
return {
y: ref(3),
z: ref(4)
}
}
})
正确答案是:
- x = 1
- y = 2
- z = undefined
当然这些只在组件外起作用,组件内部还是能获取到z
的,而且y
也还是等于 3 的。
结语
Vue 现在已经不是我以前认识的那个 Vue 了,有些功能挺好挺实用,但有些……我都不知该说啥好了,大家是怎么看待现在已经改的面目全非了的 Vue 呢?
本文首发于公众号:《前端学不动》
本文地址:https://blog.csdn.net/GetIdea/article/details/110209508