今天面试被问到这个问题,我自己思考的是让父组件做两个子组件之间的桥梁,但是我并没有去说,感觉是有些low啊,面试完了赶紧查查是怎么通信的;
就是我自己设想的这种方法也是解决问题的一种方法;
在Vue中实现兄弟组件的通讯也有几种方法,其中一种方法是让父组件允当两个子组件之间的中间件(中继);
另一种就是使用EventBus
(事件总线),它允许两个子组件之间直接通讯,而不需要涉及父组件。
这里就要好好了解下EventBus
(事件总线)的概念了;
先来看第一个方法,就是让兄弟组件通过一个共同的父组件彼此通讯。
我们还是通过示例来学习。接下来的这个示例包含父组件和两个子组件,这两个子组件是兄弟组件。单击兄弟组件上的按钮,可以看到他们之间可以相互通讯。
首先创建ParentCard
组件:
<!-- ParentCard.vue -->
<template>
<div class="card">
<div class="card-header">
<h5 v-text="theCardTitle"></h5>
<button @click="momSaidChill" v-if="stopFighting()" class="btn">停止通讯</button>
</div>
<div class="card-body">
<brother-card :messageSon="messageson" @brotherSaid="messageDaughter($event)"></brother-card>
<sister-card :messageDaughter="messagedaughter" @sisterSaid="messageSon($event)"></sister-card>
</div>
</div>
</template>
<script>
import BrotherCard from ‘./BrotherCard‘;
import SisterCard from ‘./SisterCard‘
export default {
name: ‘ParentCard‘,
data: () => ({
theCardTitle: ‘父组件‘,
messagedaughter:‘‘,
messageson:‘‘
}),
components: {
BrotherCard,
SisterCard
},
methods: {
messageDaughter(message) {
this.messagedaughter = message;
},
messageSon(message) {
this.messageson = message;
},
stopFighting() {
if (this.messagedaughter && this.messageson) {
return true
}
return false
},
momSaidChill() {
this.messagedaughter = ‘‘,
this.messageson = ‘‘
}
}
};
</script>
创建SisterCard
组件:
<!-- SisterCard.vue -->
<template>
<div class="message">
<div class="message-header">
<h5 v-text="theCardTitle"></h5>
</div>
<div class="message-body">
<p class="message-text">我是Sister组件</p>
<button @click="messageBrother" class="btn">给哥哥发消息</button>
<div v-if="messageDaughter" class="alert" v-html="messageDaughter"></div>
</div>
</div>
</template>
<script>
export default {
name: ‘SisterCard‘,
props: [‘messageDaughter‘],
data: () => ({
theCardTitle: ‘子组件2‘
}),
methods: {
messageBrother() {
this.$emit(‘sisterSaid‘, ‘妈妈说,该做作业了!(^_^)!!!‘)
}
}
}
</script>
接着创建BrotherCard
组件:
<!-- BrotherCard.vue -->
<template>
<div class="message">
<div class="message-header">
<h5 v-text="theCardTitle"></h5>
</div>
<div class="message-body">
<p class="message-text">我是Brother组件</p>
<button @click="messageSister" class="btn">给妹妹发消息</button>
<div v-if="messageSon" class="alert" v-html="messageSon"></div>
</div>
</div>
</template>
<script>
export default {
name: ‘BrotherCard‘,
props: [‘messageSon‘],
data: () => ({
theCardTitle: ‘子组件1‘
}),
methods: {
messageSister() {
this.$emit(‘brotherSaid‘, ‘妈妈说,该做作业了!(^_^)!!!‘)
}
}
}
</script>
最终效果如下:
接下来简单看看这个实现过程。
SisterCard
通过ParentCard
与BrotherCard
通讯
首先来看SisterCard
是如何与BrotherCard
通讯的。从示例中可以看出,他们两之间的通讯是通过其父组件ParentCard
作为中间媒介来进行通讯的。
我们在SisterCard
组件的<template>
中为messageBrother()
方法设置了一个@click
事件来监听该事件。
<button
methods: {
messageBrother() {
this.$emit("sisterSaid", "妈妈说,该做作业了!(^_^)!!!");
}
}
在ParentCard
的<template>
中定制了一个@sisterSaid
事件侦听器,它触发了messageSon()
方法。所以父组件在这两个兄弟组件之间起到了传递的作用。
<sister-card :messageDaughter="messagedaughter" @sisterSaid="messageSon($event)"></sister-card>
另外在ParentCard
组件中声明了messageSon()
方法,该方法接受上面发送的自定义事件,并将其设置为messageson
属性。
这样一来,ParentCard
组件中messageson
就由空字符串变成了妈妈说,该做作业了!(^_^)!!!
。
接着在ParentCard
组件自定义标签<brother-card>
通过:messageSon="messageson"
的方式将messageson
属性绑定到<brother-card>
。
<brother-card :messageSon="messageson" @brotherSaid="messageDaughter($event)"></brother-card>
这个时候在BrotherCard
组件中设置props
的属性值为messageSon
。这样就可以访问源自于SisterCard
组件的数据,并且该数据在BrotherCard
中显示。
props: ["messageSon"],
最后在BrotherCard
组件就可以使用该数据。我们可以通过v-if
指令来查看messageSon
是否有任何有用的数据,如果有,那么就在div.alert
中显示该消息:
<div v-if="messageSon" class="alert" v-html="messageSon"></div>
上面的描述过程也适用于BrotherCard
通过ParentCard
与SisterCard
进行数据通讯。
随着应用程序越来越庞大,通过父组件来传递所有内容会把事情变得越来越棘手。不过我们还有另一种选择,那就是使用EventBus
架起兄弟之间通讯的桥梁。接下来看看我们是如何利用这一点一完成兄弟组件之间的数据通讯。
我们同样基于上面的示例来做修改。接下来的示例中,ParentCard
组件包含了SisterCard
和BrotherCard
两个子组件,而且这两个子组件是兄弟组件。
首先在main.js
文件中定义一个新的eventBus
对象,其实他是一个全新的Vue实例:
// main.js
import Vue from ‘vue‘
import App from ‘./App‘
export const eventBus = new Vue()
new Vue({
el: ‘#app‘,
render: h => h(App)
})
接着在新创建的BrotherCard
组件导入main.js
:
<!-- BrotherCard.vue -->
<script>
import { eventBus } from ‘../main‘
</script>
eventBus
实例现在将成为BrotherCard
组件中发出事件的实例。现在我们可以使用eventBus.$emit
来替代上例中的this.$emit
。eventBus
是一个Vue实例,而且eventBus
有这个$emit
方法,这就是我们能够这么用的原因。这样做同样会触发相同的自定义事件名称和消息。
methods: {
messageSister() {
eventBus.$emit(‘brotherSaid‘, ‘妈妈说,该做作业了!(^_^)!!!‘)
}
}
同样可以在SisterCard
组件中引入eventBus
:
<script>
import { eventBus } from ‘../main‘
</script>
将created()
生命周期钩子添加到SisterCard
组件。在created()
钩子中添加eventBus
启动自定义事件的侦听器。当使用SisterCard
组件时,该侦听器将开始运行并且会保持运行。下面的代码只是侦听brotherSaid
自定义事件,然后触发回调,将作为自定义事件有效负载传递的消息分配给fromBrother
。
created() {
eventBus.$on(‘brotherSaid‘, (message) => {
this.fromBrother = message
})
}
这样就可以有条件地显示来自BrotherCard
的信息:
<div v-if="fromBrother" class="alert" v-html="fromBrother"></div>
上面看到的是如何通过eventBus
实现SisterCard
向BrotherCard
传递数据的方式,反之,BrotherCard
向SisterCard`传递数据也可以使用类似的方式。
最终代码如下:
<!-- SisterCard.vue -->
<template>
<div class="message">
<div class="message-header">
<h5 v-text="theCardTitle"></h5>
</div>
<div class="message-body">
<p class="message-text">我是Sister组件</p>
<button @click="messageBrother" class="btn">给哥哥发消息</button>
<div v-if="fromBrother" class="alert" v-html="fromBrother"></div>
</div>
</div>
</template>
<script>
import { eventBus } from "../main";
export default {
name: "SisterCard",
data: () => ({
theCardTitle: "Sister Card",
fromBrother: ""
}),
methods: {
messageBrother() {
eventBus.$emit("sisterSaid", "妈妈说,该做作业了!(^_^)!!!");
}
},
created() {
eventBus.$on("brotherSaid", message => {
this.fromBrother = message;
});
}
};
</script>
<!-- BrotherCard.vue -->
<template>
<div class="message">
<div class="message-header">
<h5 v-text="theCardTitle"></h5>
</div>
<div class="message-body">
<p class="message-text">我是Brother组件</p>
<button @click="messageSister" class="btn">给妹妹发消息</button>
<div v-if="fromSister" class="alert" v-html="fromSister"></div>
</div>
</div>
</template>
<script>
import { eventBus } from "../main.js";
export default {
name: "BrotherCard",
data: () => ({
theCardTitle: "Brother Card",
fromSister: ""
}),
methods: {
messageSister() {
eventBus.$emit("brotherSaid", "妈妈说,该做作业了!(^_^)!!!");
}
},
created() {
eventBus.$on("sisterSaid", message => {
this.fromSister = message;
});
}
};
</script>
最后创建的ParentCard
组件,我们可以像下面这样编码:
<!-- ParentCard -->
<template>
<div class="card">
<div class="card-header">
<h5 v-text="theCardTitle"></h5>
</div>
<div class="card-body">
<brother-card></brother-card>
<sister-card></sister-card>
</div>
</div>
</template>
<script>
import BrotherCard from "./BrotherCard";
import SisterCard from "./SisterCard";
export default {
name: "ParentCard",
data: () => ({
theCardTitle: "Parent Card"
}),
components: {
BrotherCard,
SisterCard
}
};
</script>
在本教程中,我们学习了在Vue中如何实现组件之间的通讯。通过实例看到了如何实现父组件向子组件,子组件向父组件以及兄弟组件间的数据通讯。简单的根据为:
props
可以实现父组件向子组件发送数据eventBus
来让兄弟之间组件进行数据通讯最后用一张图来简单的描述一下:
原文: https://www.w3cplus.com/vue/component-communication.html
ps:希望大家早日成为前端大神,哈哈哈
原文:https://www.cnblogs.com/zhilu/p/13851827.html