Component通信实战总结:从基础到高级的全面解析与避坑指南
组件通信又踩坑了,这次是父子组件传值
最近在做一个项目,遇到了一个挺头疼的问题:父子组件之间传值。这个问题其实挺常见的,但就是折腾了半天才搞定。
问题来了,父子组件传值不对劲
我有一个父组件 ParentComponent,里面有个按钮,点击按钮后会触发一个方法,这个方法需要更新子组件 ChildComponent 的状态。本来以为很简单,直接用 props 传值就行了,结果发现没那么简单。
排查过程,各种尝试
一开始我是这么写的:
// ParentComponent.vue
<template>
<div>
<button @click="updateChild">Update Child</button>
<ChildComponent :childData="parentData" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
data() {
return {
parentData: 'Initial Data'
};
},
methods: {
updateChild() {
this.parentData = 'Updated Data';
}
}
};
</script>
然后在子组件里接收:
// ChildComponent.vue
<template>
<div>
{{ childData }}
</div>
</template>
<script>
export default {
props: {
childData: String
}
};
</script>
按理说这样应该没问题,但子组件的状态并没有更新。这里我踩了个坑,因为 Vue 的响应式系统有时候会有点诡异。
换种方式,试试事件总线
后来试了下用事件总线来解决这个问题。Vue 3 里可以用 mitt 或者 vue-emit 这样的库来实现事件总线。我选择了 mitt,因为它简单好用。
npm install mitt
然后在主应用文件中引入并初始化:
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import mitt from 'mitt';
const emitter = mitt();
const app = createApp(App);
app.config.globalProperties.$emitter = emitter;
app.mount('#app');
在父组件里发送事件:
// ParentComponent.vue
<template>
<div>
<button @click="updateChild">Update Child</button>
<ChildComponent />
</div>
</template>
<script>
export default {
methods: {
updateChild() {
this.$emitter.emit('update-child', 'Updated Data');
}
}
};
</script>
在子组件里监听事件:
// ChildComponent.vue
<template>
<div>
{{ childData }}
</div>
</template>
<script>
export default {
data() {
return {
childData: 'Initial Data'
};
},
created() {
this.$emitter.on('update-child', (data) => {
this.childData = data;
});
}
};
</script>
这样终于解决了问题,子组件的状态能够正确更新了。
技术细节和原理
这里稍微聊聊为什么最初的方法不行。Vue 的响应式系统是基于数据的依赖追踪机制,当你通过 props 传递数据时,如果父组件的数据发生变化,Vue 会自动更新子组件的状态。但有时候由于一些原因(比如缓存、优化等),这种机制可能会失效。
而使用事件总线则是一种更直接的方式,通过事件来显式地通知子组件进行状态更新。这种方式虽然有点绕,但在某些情况下确实更可靠。
总结一下,踩坑后的经验
以上是我在这次开发中遇到的关于父子组件通信的问题和解决方案。事件总线虽然不是最优解,但在这个场景下确实有效。如果你有更好的方案,欢迎在评论区交流。
这个技巧的拓展用法还有很多,后续会继续分享这类博客。希望对你有帮助!
本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。

暂无评论