<template> <button @click="increment">{{ count }}</button> </template>使用 ref 定义 count 变量和 increment 方法:
let count = ref(0) function increment() { count.value++ }而使用响应性语法糖,我们可以像这样书写代码:
let count = $ref(0) function increment() { count++ }Vue 的响应性语法糖是一个编译时的转换步骤,$ref() 方法是一个编译时的宏命令,它不是一个真实的、在运行时会调用的方法,而是用作 Vue 编译器的标记,表明最终的 count 变量需要是一个响应式变量。响应式的变量可以像普通变量那样被访问和重新赋值,但这些操作在编译后都会变为带 .value 的 ref。所以上面例子中的代码也会被编译成使用 ref 定义的语法。
ref -> $ref computed -> $computed shallowRef -> $shallowRef customRef -> $customRef toRef -> $toRef可以使用 `$()` 宏来将现存的 `ref` 转换为响应式变量。
const a = ref(0) let count = $(a) count++ console.log(a.value) // 1可以使用 `$$()` 宏来将任何对响应式变量的引用都会保留为对相应 `ref` 的引用。
let count = $ref(0) console.log(isRef($$(count))) // true$$() 也适用于已解构的 props,因为它们也是响应式的变量。编译器会高效地通过 toRef 来做转换:
const { count } = defineProps<{ count: number }>() passAsRef($$(count))
// vite.config.js export default { plugins: [ vue({ reactivityTransform: true }) ] }注意 reactivityTransform 现在是一个插件的顶层选项,而不再是位于 script.refSugar 之中了,因为它不仅仅只对 SFC 起效。
// vue.config.js module.exports = { chainWebpack: (config) => { config.module .rule('vue') .use('vue-loader') .tap((options) => { return { ...options, reactivityTransform: true } }) } }如果是 webpack + vue-loader 构建,需要 vue-loader@>=17.0.0,目前仅对 SFC 起效。
// webpack.config.js module.exports = { module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { reactivityTransform: true } } ] } }可选,`tsconfig.json` 文件中添加如下代码, 不然会报错 `TS2304: Cannot find name '$ref'.`,虽然不影响使用,但是会影响开发体验:
// webpack.config.js module.exports = { module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { reactivityTransform: true } } ] } }可选,`eslintrc.cjs` 文件中添加如下代码,不然会提示 `ESLint: '$ref' is not defined.(no-undef)`:
module.exports = { globals: { $ref: "readonly", $computed: "readonly", $shallowRef: "readonly", $customRef: "readonly", $toRef: "readonly", } };当启用响应性语法糖时,这些宏函数都是全局可用的、无需手动导入。也可以在 vue 文件中显式引入 `vue/macros`,这样就不用配置第二和第三步中的 `tsconfig.json` 和 `eslintrc` 了。
import { $ref } from 'vue/macros' let count = $ref(0)
3.4:该功能将从核心中删除,除非使用 Vue Macros,否则将不再有效。
虽然 Reactivity Transform 会从官方包中移除,但我认为这是一个很好的尝试。写得好。我喜欢详细的 RFC 和基于用户反馈的客观评估。最后的结论很有道理。不要让完美成为优秀的敌人。虽然我很享受这个功能带来的便利,但我在实际使用中确实发现了这个潜在的碎片问题。在未来的版本中删除此功能可能不太情愿,但工程师应该认真对待。