使用Vue Composition API / Vue 3监听props变化
技术背景
在Vue 3中引入了Composition API,它提供了更灵活的方式来组织和复用组件逻辑。在开发过程中,经常需要监听组件props
的变化以执行相应的操作,但Vue Composition API RFC参考站点和相关文档中并没有明确给出监听props
变化的示例。
实现步骤
1. 直接监听单个prop
通过传入一个返回prop
值的函数作为watch
的第一个参数来监听单个prop
的变化。示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { watch } from 'vue';
export default { props: { selected: { type: [String, Number], required: true } }, setup(props) { watch(() => props.selected, (newValue, oldValue) => { console.log('Watch props.selected function called with args:', newValue, oldValue); });
return {}; } };
|
2. 监听多个prop
可以传入一个包含多个返回prop
值的函数的数组来监听多个prop
的变化。示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import { watch } from 'vue';
export default { props: { prop1: { type: String, required: true }, prop2: { type: Number, required: true } }, setup(props) { watch([() => props.prop1, () => props.prop2], ([newProp1, newProp2], [oldProp1, oldProp2]) => { console.log('Prop1 changed from', oldProp1, 'to', newProp1); console.log('Prop2 changed from', oldProp2, 'to', newProp2); });
return {}; } };
|
3. 监听复杂类型的prop
对于对象或数组类型的prop
,可以使用deep
选项来进行深度监听。示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { watch } from 'vue';
export default { props: { complexType: { type: Object, default: () => ({}) } }, setup(props) { watch(() => props.complexType, (newValue, oldValue) => { console.log('Complex type prop changed:', newValue, oldValue); }, { deep: true });
return {}; } };
|
4. 将props
对象转换为Ref
对象
使用toRefs
将props
对象转换为Ref
对象,然后可以直接将Ref
对象作为watch
的第一个参数。示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import { watch, toRefs } from 'vue';
export default { props: { title: { type: String, required: true } }, setup(props) { const { title } = toRefs(props);
watch(title, (newValue, oldValue) => { console.log('Title prop changed from', oldValue, 'to', newValue); });
return {}; } };
|
核心代码
以下是一个完整的示例,展示了如何在Vue 3中使用Composition API监听props
的变化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <template> <div> <p>Prop value: {{ selected }}</p> </div> </template>
<script> import { watch } from 'vue';
export default { props: { selected: { type: [String, Number], required: true } }, setup(props) { watch(() => props.selected, (newValue, oldValue) => { console.log('Prop changed from', oldValue, 'to', newValue); });
return {}; } }; </script>
|
最佳实践
- 避免不必要的监听:大多数情况下,直接在模板或
setup
函数中使用props
即可,Vue会自动处理响应式更新,无需手动监听。 - 使用
toRefs
或toRef
:当需要保留props
的响应式时,可以使用toRefs
或toRef
将props
转换为Ref
对象。 - 深度监听要谨慎:对于复杂类型的
prop
,使用deep
选项进行深度监听可能会影响性能,应谨慎使用。
常见问题
1. 监听props
时传入错误类型的参数
在使用watch
监听props
时,如果直接传入props
对象或prop
的值,而不是一个返回prop
值的函数,会导致监听失败。例如:
1 2 3 4
| watch(props.selected, (newValue, oldValue) => { console.log('Watch props.selected function called with args:', newValue, oldValue); });
|
正确的做法是传入一个返回prop
值的函数:
1 2 3 4
| watch(() => props.selected, (newValue, oldValue) => { console.log('Watch props.selected function called with args:', newValue, oldValue); });
|
2. 监听复杂类型的prop
时未使用deep
选项
如果要监听对象或数组类型的prop
的内部变化,需要使用deep
选项,否则只有当prop
的引用发生变化时才会触发监听回调。例如:
1 2 3 4 5 6 7 8 9
| watch(() => props.complexType, (newValue, oldValue) => { console.log('Complex type prop changed:', newValue, oldValue); });
watch(() => props.complexType, (newValue, oldValue) => { console.log('Complex type prop changed:', newValue, oldValue); }, { deep: true });
|