在最新的版本3.5x中,对props的能力也进行了加强。下面,我们具体看下有哪些变化,给我们带来的新的体验!
体验一
- 3.5之前解构props的效果
// 子组件
<template>
<div>
<h1>响应式props</h1>
<p>{{ count }}</p>
</div>
</template>
<script setup>
import { watch, watchEffect } from "vue";
const { count } = defineProps(["count"]);
watchEffect(() => {
console.log("count", count);
});
watch(
() => count,
newVal => {
console.log("count", newVal);
}
);
</script>
// 父组件
<template>
<div>
<ChildProps :count="count" />
<button @click="count++">Click me</button>
</div>
</template>
<script setup>
import ChildProps from "@/components/ChildProps";
import { ref } from "vue";
const count = ref(0);
</script>
- 代码解析
- 子组件解构父组件传来的count数据,在子组件中是无法
watch
到count
的更新的,如上图 - 同样的代码,只需更换vue版本到3.5,监听就会生效了,如下图
- 解析出来的
count
,在进行watch
时,不能直接传count
,要用对应的get
- 反例:这并不会按预期工作,因为它等价于
watch(props.foo, ...)
——我们给watch
传递的是一个值而不是响应式数据源。实际上,Vue 的编译器会捕捉这种情况并发出警告。
watch(count, /* ... */)
- 子组件解构父组件传来的count数据,在子组件中是无法
体验二
将我们结构出来的props属性,传给自定义的hooks,保持数据的响应性,那怎么做?
- 实现效果
- 代码实现
// 自定义hooks
import { toValue, ref, watchEffect } from "vue";
export function useCountAdd(num) {
let computedCount = ref(0);
watchEffect(() => {
computedCount.value = toValue(num) + 1;
});
return computedCount;
}
- 父组件
<template>
<div>
<h1>响应式props</h1>
<p>{{ count }}</p>
<p>{{ newCount }}</p>
</div>
</template>
<script setup>
import { useCountAdd } from "@/hooks/useCount";
const { count } = defineProps(["count"]);
// (1)
const newCount = useCountAdd(count);
</script>
(1):如果直接传递解构出来的count
,我们的页面是不能及时响应更新的。
正例:
const newCount = useCountAdd(() => count);