1 各种组件之间通信方式
2 祖孙组件之间通信
对于组件层次结构比较深的的情况,祖先组件使用 provide
选项来提供数据,子孙组件使用 inject
选项来使用这些数据。
<body>
<div id="app"></div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { createApp, components } = Vue;
// 子孙组件
const childrenComponent = {
template: "<div>{{ name }}</div>",
inject: ["name"]
};
// 父组件
const parentComponent = {
template: "<children-component></children-component>",
components: {
childrenComponent,
},
};
// 根组件/祖先组件
const Root = {
template: "<parent-component></parent-component>",
provide: {
name: 'rootName',
},
components: {
parentComponent,
},
};
const app = createApp(Root);
app.mount("#app");
</script>
</body>
但是,如果我们尝试在此处 provide
一些祖先组件的实例 property
,这将不起作用的:
// 错误写法
const Root = {
template: "<parent-component></parent-component>",
data: function () {
return {
name: "RootComponent",
};
},
provide: {
name: this.name, // 无法传递给子孙组件
},
components: {
parentComponent,
},
};
// 正确写法
// 如果要访问组件实例 property,需要将 provide 转换为返回对象的函数。
const Root = {
template: "<parent-component></parent-component>",
data: function () {
return {
name: "RootComponent",
};
},
provide(){
return {
name: this.name,
}
},
components: {
parentComponent,
},
};
🚨 注意:上面代码通过 provide
和 inject
实现了祖先组件和子孙组件的通信,但是这种通信是单向的,也就是说,数据只能由祖先组件传递给子孙组件。
3 父子组件之间通信
对于父子组件之间的通信,父组件可以使用 props
把数据传递给子组件,子组件通过 $emit()
把数据传递给父组件。
1️⃣ 父组件传递数据给子组件
<body>
<div id="app"></div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { createApp, components } = Vue;
const childrenComponent = {
template: "<div>{{ des }}</div>",
props: ['des'],
};
const parentComponent = {
template: "<children-component des='我是父组件传递过来的数据'></children-component>",
components: {
childrenComponent,
},
};
const Root = {
template: "<parent-component></parent-component>",
components: {
parentComponent,
},
};
const app = createApp(Root);
app.mount("#app");
</script>
</body>
上面代码中,子组件通过 props
选项来接收父组件传递过来的数据。
2️⃣ 子组件传递数据给父组件
步骤一已经实现数据从父组件传递到子组件,那么如何实现数据从子组件传递到父组件呢?
子组件可以通过 $emit()
来触发事件,并把需要传递给父组件的数据当做参数传递给父组件。
<body>
<div id="app"></div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { createApp, components } = Vue;
const childrenComponent = {
template: "<div><button @click='sendToParent'>传递数据</button></div>",
methods: {
sendToParent() {
let message = "我是子组件传递过来的数据";
this.$emit("sendMessage", message);
},
},
};
const parentComponent = {
template:
"<children-component @sendMessage='getMessage'></children-component>",
components: {
childrenComponent,
},
methods: {
getMessage(e) {
console.log(e); // 我是子组件传递过来的数据
},
},
};
const Root = {
template: "<parent-component></parent-component>",
components: {
parentComponent,
},
};
const app = createApp(Root);
app.mount("#app");
</script>
</body>
4 兄弟组件之间通信
1️⃣ EventBus
<body>
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const eventBus = new Vue();
const brotherComponent = {
template: "<div><button @click='sendToSister'>传递数据</button></div>",
created() {
eventBus.$on("sendMessageToBrother", (e) => {
console.log(e);
});
},
methods: {
sendToSister() {
let message = "我是哥哥传递过来的数据";
eventBus.$emit("sendMessageToSister", message);
},
},
};
const sisterComponent = {
template: "<div><button @click='sendToBrother'>传递数据</button></div>",
created() {
eventBus.$on("sendMessageToSister", (e) => {
console.log(e);
});
},
methods: {
sendToBrother() {
let message = "我是妹妹传递过来的数据";
eventBus.$emit("sendMessageToBrother", message);
},
},
};
const rootComponent = {
template: `<div>
<brother-component></brother-component>
<sister-component></sister-component>
</div>
`,
components: {
brotherComponent,
sisterComponent,
},
};
new Vue({
el: "#app",
template: "<root-component></root-component>",
components: {
rootComponent,
},
});
</script>
</body>
上面代码中,使用 eventBus.$emit()
来替代 this.$emit()
触发自定义事件。在需要接收数据的组件的 created
钩子函数使用 eventBus.$on()
监听事件。
2️⃣ 利用父组件充当中间人
和父子组件通信原理相同。
5 任意组件之间通信
任意组件之间通信的方式有2种:Vuex
和 EventBus
。