Vue 的响应性语法糖

536936a811e45a560e618fa81b1b2217.png

ref vs. 响应式变量

自从引入组合式 API 的概念以来,一个主要的未能解决的问题就是 ref 和响应式对象的使用方式。到处使用 .value 无疑是很繁琐的,并且在没有类型系统的帮助时很容易漏掉。

Vue 的响应性语法糖是一个编译时的转换过程,使我们可以像这样书写代码:

<script setup>
let count = $ref(0)


console.log(count)


function increment() {
  count++
}
</script>


<template>
  <button @click="increment">{{ count }}</button>
</template>

这里的这个 $ref() 方法是一个编译时的宏命令:它不是一个真实的、在运行时会调用的方法。而是用作 Vue 编译器的标记,表明最终的 count 变量需要是一个响应式变量。

响应式的变量可以像普通变量那样被访问和重新赋值,但这些操作在编译后都会变为带 .value 的 ref。比如上面例子中 <script> 部分的代码就被编译成了下面这样:

import { ref } from 'vue'


let count = ref(0)


console.log(count.value)


function increment() {
  count.value++
}

计算属性

<script setup>
import { reactive, computed } from 'vue'


const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})


// 一个计算属性 ref
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})


const publishedBooksMessageZh = computed(() => {
  const chinese = {"Yes": "是", "No": "否"}
  return chinese[publishedBooksMessage.value]
})
</script>


<template>
  <p>Has published books:</p>
  <span>{{ publishedBooksMessage }}</span>
  <span>{{ publishedBooksMessageZh }}</span>
</template>

我们在这里定义了一个计算属性 publishedBooksMessage。computed() 方法期望接收一个 getter 函数,返回值为一个计算属性 ref。和其他一般的 ref 类似,你可以通过 publishedBooksMessage.value 访问计算结果。计算属性 ref 也会在模板中自动解包,因此在模板表达式中引用时无需添加 .value

计算属性宏函数

<script setup>
import { reactive, computed } from 'vue'


const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})


const publishedBooksMessage = $computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})


const publishedBooksMessageZh = $computed(() => {
  const chinese = {"Yes": "是", "No": "否"}
  return chinese[publishedBooksMessage]
})
</script>


<template>
  <p>Has published books:</p>
  <span>{{ publishedBooksMessage }}</span>
</template>

每一个会返回 ref 的响应性 API 都有一个相对应的、以 $ 为前缀的宏函数。包括以下这些 API:

ref -> $ref
computed -> $computed
shallowRef -> $shallowRef
customRef -> $customRef
toRef -> $toRef

响应性语法糖目前是一个实验性功能,默认是禁用的,需要显式选择使用。在最终确定前仍可能发生变化,你可以查看 GitHub 上的提案与讨论来关注和跟进最新进展。