传递含响应式属性的对象作为Prop时,子组件onUpdated为何触发?
为什么传递响应式对象作为Prop会触发子组件的onUpdated钩子?
场景复现
- 子组件
Comp.vue:仅在onUpdated生命周期钩子中打印updated component,无其他响应式数据或模板逻辑 - 父组件
App.vue:挂载Comp组件,自身onUpdated钩子打印updated parent,页面中的input绑定到响应式变量text - 现象:
- 初始状态下,在
input中输入内容只会触发父组件的onUpdated钩子 - 当给
Comp传递一个包含响应式属性的对象{ data }作为Prop后,输入内容会同时触发父子组件的onUpdated钩子
- 初始状态下,在
原因分析
这本质是Vue响应式更新机制的特性:
- 组件更新的触发条件:Vue组件会在自身的响应式依赖(Props、data、computed等)发生变化时重新渲染,渲染完成后触发
onUpdated钩子。 - 初始无Prop的情况:子组件没有接收任何Prop,也没有自身的响应式数据,父组件的
text变化只会触发父组件的依赖更新,子组件不存在与父组件相关的依赖追踪,因此不会重新渲染。 - 传递响应式对象Prop的情况:
- 当父组件将响应式对象作为Prop传递给子组件时,子组件的实例会将这个响应式对象纳入自身的依赖系统。
- 父组件因
text变化重新渲染时,会重新计算子组件的Prop值。由于该Prop是响应式对象,Vue的响应式系统会检测到它与父组件的响应式上下文关联,即使子组件的模板中没有直接使用该Prop的任何属性,也会触发子组件的重新渲染,进而调用onUpdated钩子。
用computed规避的原理
通过computed属性传递Prop时,我们可以生成一个与原响应式对象解耦的派生值:
- 如果返回的是原响应式对象的属性快照(比如
computed(() => ({ ...data }))),传递给子组件的是普通非响应式对象,父组件更新时只有当快照内容变化才会触发子组件更新;若text变化不影响快照内容,子组件就不会更新。 - 如果返回的是响应式对象的某个具体属性,子组件只会追踪该单个属性的变化,而非整个对象的关联依赖,避免不必要的更新。
内容的提问来源于stack exchange,提问作者8ctavio
相关产品推荐
相关产品推荐

