Vue3.5+ 响应式 Props 解构
你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。
在 Vue 3.5+ 中,响应式 Props 解构已经稳定并默认启用。这意味着在 <script setup>
中从 defineProps
调用解构的变量现在是响应式的。这一改进大大简化了声明带有默认值的 props 的方式,并使得在子组件中直接使用解构后的 props 变量时能够保持响应性。
最新语法
Vue 的响应系统基于属性访问跟踪状态的使用情况。例如,在计算属性或侦听器中访问 props.foo
时,foo
属性将被跟踪为依赖项。
因此,在以下代码的情况下:
const { foo } = defineProps(["foo"]);
watchEffect(() => {
// 在 3.5之前只运行一次
// 在 3.5+ 中在 "foo" prop 变化时重新执行
console.log(foo);
});
在 3.5 之前的版本中, foo
是一个实际的常量,永远不会改变。在 3.5 及以上版本,当在同一个 <script setup>
代码块中访问由 defineProps
解构的变量时,Vue 编译器会自动在前面添加 props.
。因此,上面的代码等同于以下代码:
const props = defineProps(["foo"]);
watchEffect(() => {
// `foo` 由编译器转换为`props.foo`
console.log(props.foo);
});
此外,你可以使用 JavaScript 原生的默认值语法声明 props 默认值。这在使用基于类型的 props 声明时特别有用。
const { foo = 'hello' } = defineProps<{ foo?: string }>()
watch 监听解构的 props
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 中。
示例一 watchEffect
3.5+ 版本<template>
<div>{{ content }}</div>
</template>
<script setup>
import { defineProps, watchEffect } from "vue";
// 解构 props,注意这里的变量是响应式的
const { content } = defineProps(["content"]);
watchEffect(() => {
// 在 3.5 之前只运行一次
// 在 3.5+ 中在 "content" prop 变化时重新执行
console.log(content);
});
</script>
3.5 前的版本
<template>
<div>{{ content }}</div>
</template>
<script setup>
import { defineProps, watchEffect } from "vue";
const props = defineProps(["content"]);
watchEffect(() => {
console.log(props.content);
});
</script>
示例二 watch
3.5+ 版本<template>
<div>{{ content }}</div>
</template>
<script setup>
import { defineProps, watch } from 'vue'
const { content } = defineProps(['content'])
watch(
() => content,
(newValue) => {
console.log(newValue)
)
</script>
3.5 前的版本
<template>
<div>{{ content }}</div>
</template>
<script setup>
import { defineProps, watch } from 'vue'
const props = defineProps(['content'])
watch(
() => props.content,
(newValue) => {
console.log(newValue)
)
</script>
示例三 computed
3.5+ 版本<template>
<div>
{{ content }}
<br />
{{ formatContent }}
</div>
</template>
<script setup>
import { defineProps, computed } from "vue";
const { content } = defineProps(["content"]);
const formatContent = computed(() => content.toUpperCase());
</script>
3.5 前的版本
<template>
<div>
{{ content }}
<br />
{{ formatContent }}
</div>
</template>
<script setup>
import { defineProps, computed } from "vue";
const props = defineProps(["content"]);
const formatStr = computed(() => props.content.toUpperCase());
</script>
好了,分享结束,谢谢点赞,下期再见。