前言
在 Vue.JS 中,兄弟组件之间的通信由于缺乏直接的父子关系而变得相对复杂。然而,Vue提供了多种机制来实现这种同级组件间的有效数据共享与通信。Vue2常见的方法包括使用事件总线(Event Bus)或 Vuex 状态管理库,这些方案能够帮助我们轻松地在没有直接关联的组件之间传递信息和状态,确保应用逻辑的一致性和可维护性。兄弟组件,就是同级别的组件。
一. 事件总线
第一种,事件总线(Event Bus)方法。请看
描述:首先在main.js文件中定义一个新的bus对象,然后挂载在原型链上,生成一个全新的Vue实例,通过bus.$emit('自定义的事件名',要传的值)传值,通过bus.$on来接收,具体步骤如下。
1. 初始化事件总线
- 在项目的入口文件
main.js
或类似位置,创建一个新的 Vue 实例作为事件总线。 - 将此实例附加到 Vue 原型上,使所有 Vue 组件都能通过
this.$bus
访问它。
//写在main.js中
Vue.prototype.$bus = new Vue()
2. 发送数据,在发送方组件触发事件
- 在需要发送数据的组件(如
sister.vue
)中,定义一个方法用于触发事件。 - 使用
$bus
的$emit
方法触发事件,传入事件名(如 brotherEvent)和要发送的数据。
//sister.vue
//在方法中调用事件
methods:{
choseEvent(){
this.$bus.$emit('brotherEvent',this.data)
}
}
3. 接收数据,在接收方组件监听事件
- 在接收数据的组件(如
brother.vue
)中,使用created
生命周期钩子来设置事件监听器。 - 声明并监听事件 brotherEvent,使用
$bus
的$on
方法监听事件,指定事件名和回调函数,该函数将在事件触发时执行并接收传递的数据。
//brother.vue
//在同级别组件中声明监听事件
created(){
this.$bus.$on('brotherEvent', res=>{
console.log(res) // res就是sister.vue里choseEvent方法传递的值data
})
}
4. 清理事件监听器
- 当组件销毁时,确保取消所有注册的事件监听器,避免内存泄漏。
- 可以在
beforeDestroy
生命周期钩子中使用$bus
的$off
方法来移除监听器。
beforeDestroy() {
this.$bus.$off('brotherEvent');
}
5. 整体流程
事件总线在 Vue.js 中实现兄弟组件间通信的整体流程。请看
初始化事件总线: 在项目的启动文件(通常是
main.js
),创建一个新的 Vue 实例作为事件总线。这个实例将作为消息的中心点,任何组件都可以向它发送和接收消息。将这个实例挂载到 Vue 的原型链上,确保所有的 Vue 组件都可以通过this.$bus
来访问它。发送数据的组件: 需要发送数据的组件(例如
sister.vue
)定义一个方法,在适当的时候触发一个事件。通过调用事件总线的$emit
方法,传递事件名称和需要发送的数据。这相当于告诉事件总线:“嘿,我有一些信息需要传递出去。”接收数据的组件: 另一个组件(例如
brother.vue
),在它的生命周期钩子created
中,监听事件总线上特定的事件。通过调用事件总线的$on
方法,它告诉事件总线:“如果有人发出名为 ‘brotherEvent’ 的事件,请通知我,并把相关数据传递给我。”这样,一旦事件被触发,接收组件就可以接收到发送组件发送的数据。清理监听器: 为了避免内存泄漏,当一个组件不再需要监听事件时,应当在适当的时机(如组件销毁前)取消事件监听。这通常在组件的
beforeDestroy
生命周期钩子中完成,通过调用事件总线的$off
方法来移除先前注册的事件监听器。
兄弟组件能够通过事件总线相互通信,即使它们之间没有直接的父子关系。这种模式在 Vue.js 中广泛用于解耦组件,使它们能够独立地工作,同时又能够在需要时相互协作。
二. 桥接通信
第二种,桥接通信的中间件方法。请看
描述:原理就是通过父组件作为中间件来通讯,结合子传父,父再传子,实现同级别间的兄弟组件传值,具体步骤如下。
1. 添加方法
首先在父组件引入两个子组件,并且给子组件添加自定义方法,如下。请看
//father.vue
//组件引入
import brother from "./components/brother.vue";
import sister from "./components/sister.vue";
//组件注册
components: {
brother,
sister,
},
//组件使用
//在子组件上添加自定义方法 @defineBrother="choseBrother"
<brother @defineBrother="choseBrother" />
//在子组件上添加自定义方法 @defineSister="choseSister"
<sister @defineSister="choseSister" />
2. 调用方法
在子组件brother.vue中使用$emit调用子组件的自定义方法,并且传值。请看
//brother.vue组件
<button @click="choseBrotherBtn">兄弟按钮</button>
data() {
return {
brotherMsg: [1, 2, 3, 4],
};
},
methods: {
choseBrotherBtn() {
this.$emit("defineBrother", this.brotherMsg);
},
},
子组件sister.vue同样,使用$emit调用子组件的自定义方法,并且传值
//sister.vue组件
<button @click="choseSisterBtn">姐妹按钮</button>
data() {
return {
sisterMsg: { name: "xxx" },
};
},
methods: {
choseSisterBtn() {
this.$emit("defineSister", this.sisterMsg);
},
},
3. 接收数据
父组件通过自定义方法,接收来自子组件传递的数据。请看
//father.vue接收数据
data() {
return {
data: "",
msg: "",
};
},
methods: {
choseBrother(value) {
console.log(value);//这里的value就是兄弟组件传过来的数组数据brotherMsg
this.data = value;//赋值给父级组件data
},
choseSister(value) {
console.log(value);//这里的value就是姐妹组件传过来的数据对象sisterMsg
this.msg = value;//赋值给父级组件msg
},
},
4. 传递数据
父组件接收到数据以后,再通过父传子,传递对应数据。请看
//father.vue
//父传子:sendFather="msg";
//把sister.vue中的数据sisterMsg 传给brother;
<brother :sendFather="msg" @defineBrother="choseBrother" />
//父传子 :sendSister="data";
//把brother.vue中的数据brotherMsg 传给sister;
<sister :sendSister="data" @defineSister="choseSister" />
5. 再次接收数据
最后使用props再次接收数据,完成传值。请看
//兄弟组件 接收来自 姐妹组件 的 对象数据sisterMsg
props:["sendBrother"],
{{sendBrother}}
//姐妹组件 接收来自 兄弟组件 的 数组数据brotherMsg
props:["sendSister"],
{{sendSister}}
到这里,兄弟组件(同级组件)传值通讯成功。
6. 兄弟组件间通信,可以叫做“通过父组件通信”或者“桥接通信”的整体流程:
父组件引入与注册子组件:
- 父组件(
father.vue
)导入兄弟组件(brother.vue
)和姐妹组件(sister.vue
)。- 注册这两个组件,使它们成为父组件的局部子组件。
- 在父组件模板中,通过绑定自定义事件处理器(
@defineBrother="choseBrother"
和@defineSister="choseSister"
)来监听子组件的事件。子组件触发事件并传递数据:
- 兄弟组件(
brother.vue
)和姐妹组件(sister.vue
)各自有一个按钮,点击按钮会触发方法(choseBrotherBtn
和choseSisterBtn
)。- 这些方法使用
$emit
发射自定义事件(defineBrother
和defineSister
),并将组件的数据(brotherMsg
和sisterMsg
)作为参数传递给父组件。父组件接收并处理子组件数据:
- 父组件中定义的方法(
choseBrother
和choseSister
)接收到来自子组件的数据,并将它们分别存储在父组件的数据属性(data
和msg
)中。父组件向下传递数据:
- 父组件通过属性绑定(
:sendFather="msg"
和:sendSister="data"
)将之前接收的数据传递给兄弟组件和姐妹组件。子组件接收父组件传递的数据:
- 兄弟组件和姐妹组件通过声明接收属性(
props
),分别接收父组件传递的姐妹数据(sendBrother
)和兄弟数据(sendSister
)。- 这些数据可以在组件模板中通过插值表达式(
{{ sendBrother }}
和{{ sendSister }}
)显示出来。
兄弟组件 和 姐妹组件 能够通过父组件实现数据的双向通信,大致流程就是:先是子组件向父组件发送数据,然后父组件再将数据转发给另一个子组件。这种方式有效地利用了 Vue.js 的组件通信机制,确保了组件之间的解耦和数据的有序流动。