以前我们对Props直接进行解构赋值是会失去响应式的,需要配合使用toRefs或者toRef解构才会有响应式,那么就多了toRefs或者toRef这工序,而最新Vue3.5版本已经不需要了。
了解一下 toRef() 的使用:
1.可以将值、refs 或 getters 规范化为 refs (3.3+)。2.也可以基于响应式对象上的一个属性,创建一个对应的 ref。这样创建的 ref 与其源属性保持同步:改变源属性的值将更新 ref 的值,反之亦然。
toRef() 这个函数在你想把一个 prop 的 ref 传递给一个组合式函数时会很有用:
import { toRef } from 'vue'
const props = defineProps(/* ... */)
// 将 `props.foo` 转换为 ref,然后传入
// 一个组合式函数
useSomeFeature(toRef(props, 'foo'))
// getter 语法——推荐在 3.3+ 版本使用
useSomeFeature(toRef(() => props.foo))
Vue 的响应系统基于属性访问跟踪状态的使用情况。例如,在计算属性或侦听器中访问 props.foo 时,foo 属性将被跟踪为依赖项。
因此,在以下代码的情况下:
const { foo } = defineProps(['foo'])
watchEffect(() => {
// 在 3.5 之前只运行一次
// 在 3.5+ 中在 "foo" prop 变化时重新执行
console.log(foo)
})
在 3.4 及以下版本,foo 是一个实际的常量,永远不会改变。在 3.5 及以上版本,当在同一个 代码块中访问由 defineProps 解构的变量时,Vue 编译器会自动在前面添加 props.。因此,上面的代码等同于以下代码:
const props = defineProps(['foo'])
watchEffect(() => {
// `foo` 由编译器转换为 `props.foo`
console.log(props.foo)
})
此外,你可以使用 JavaScript 原生的默认值语法声明 props 默认值。这在使用基于类型的 props 声明时特别有用。
const { foo = 'hello' } = defineProps<{ foo?: string }>()
如果你希望在 IDE 中在解构的 props 和普通变量之间有更多视觉上的区分,Vue 的 VSCode 扩展提供了一个设置来启用解构 props 的内联提示。
将解构的 props 传递到函数中
当我们将解构的 prop 传递到函数中时,例如:
const { foo } = defineProps(['foo'])
watch(foo, /* ... */)
这并不会按预期工作,因为它等价于 watch(props.foo, ...) ——我们给 watch 传递的是一个值而不是响应式数据源。实际上,Vue 的编译器会捕捉这种情况并发出警告。
与使用 watch(() => props.foo, ...) 来侦听普通 prop 类似,我们也可以通过将其包装在 getter 中来侦听解构的 prop:
watch(() => foo, /* ... */)
此外,当我们需要传递解构的 prop 到外部函数中并保持响应性时,这是推荐做法:
useComposable(() => foo)
外部函数可以调用 getter (或使用 toValue 进行规范化) 来追踪提供的 prop 变更。例如,在计算属性或侦听器的 getter 中。