组件是 vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互传递,因此组件之间的通信很重要。一般来说,组件可以有以下几种关系

如上图所示,A 和 B、B 和 C、B 和 D 都是父子关系,C 和 D 是兄弟关系,A 和 C 是隔代关系(可能隔多代)。
Vue组件间的通信方式
● props和$emit(常用)
● $ attrs和$listeners
● 中央事件总线(非父子组件间通信)
● v-model
● provide和inject
● $ parent和$children
● vuex
1、props和$emit
父组件向子组件:父组件中使用子组件时用v-bind绑定数据,子组件通过prop接收数据。
子组件向父组件:子组件通过$ emit触发事件,父组件通过v-on监听事件
父组件App.vue
<template>
<div id="app">
//使用v-bind进行父组件传值给子组件,使用v-on绑定事件感知子组件传递来的数据
<users v-bind:mess="users" v-on:childToParent="getData"></users> //v-on绑定的事件名要与子组件中定义的一致!
</div>
</template>
<script>
import Users from "./components/Users" //导入子组件
export default {
name: 'App',
data(){
return{
users:["Henry","Bucky","Emily"],
message=''
}
},
components:{
"users":Users //注册子组件
},
methods:{
//在methods中定义函数接收子组件传递来的数据
getData(val){
this.message = val;
}
}
}
</script>
子组件User.vue
<template>
<div class="hello">
<input type="text" v-model="val" v-on:input="passData(val)"> //绑定一个事件以触发传递数据给父组件
<ul>
<li v-for="user in mess">{{user}}</li> //遍历从父组件传递过来的值,然后呈现到页面
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data:{
val:''
},
props:{ //props定义父组件向子组件传递的数据
mess:{
type:Array,
required:true
}
},
methods:{
//在methods中定义函数向父组件传值
passData(val) {
//两个参数:自定义事件名,传递的值
this.$emit("childToParent",val);
}
}
}
</script>
(1)父组件传递了mess数据给子组件,并且通过v-on绑定了一个childToParent事件来监听子组件的触发事件;
(2)子组件通过props得到相关的mess数据,最后通过this.$emit触发了childToParent事件。
2、中央事件总线 EventBus
这种方法通过一个空的 Vue 实例EventBus作为中央事件总线(事件中心),通过 EventBus.$ emit来触发事件和EventBus.$on 来监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。
(1)创建中央事件总线EventBus
①在main.js中创建
//定义中央事件总线
const EventBus = new Vue();
// 将中央事件总线赋值到 Vue.prototype 上(作为全局属性),这样所有组件都能访问到了
Vue.prototype.$EventBus = EventBus;
把中央事件总线EventBus作为Vue的全局属性
②自定义js文件

在src下创建eventBus.js文件,并定义央事件总线实例对象
//eventBus.js文件内容
import Vue from "vue"
const EventBus=new Vue() //定义中央事件总线
export default EventBus //导出中央事件总线供其他组件访问
(2)在需要通信的组件中使用中央事件总线EventBus
①使用作为全局属性的中央事件总线
组件A.vue
<template>
<div>
<button @click="send">将数据发送给B组件</button>
</div>
</template>
<script>
export default {
name: "A",
data(){
return{
message:"你好,组件B"
}
},
methods:{
send() {
//使用全局属性的中央事件总线触发事件
this.$EventBus.$emit('data-a', message); //事件名,传递参数
}
}
}
</script>
<style scoped>
</style>
组件B.vue
<template>
<div>
<h3>来自组件A的值:{{message}}</h3>
</div>
</template>
<script>
export default {
name: "B",
data(){
return{
message:''
}
},
//在mounted中定义接收数据
mounted() { //在模板编译完成后执行
//使用全局属性的中央事件总线监听事件
this.$EventBus.$on('data-a',val => {
console.log(val)val
this.message = val;
})
}
}
</script>
<style scoped>
</style>
②使用作为vue实例对象的中央事件总线
这种情况下,必须先在需要通信的组件中导入中央事件总线实例。
组件A
<template>
<div>
<button @click="send">将数据发送给B组件</button>
</div>
</template>
<script>
//导入中央事件总线实例
import EventBus from "../eventBus";
export default {
name: "A",
data(){
return{
message:"你好,组件B"
}
},
methods:{
send() {
//使用中央事件总线实例对象触发事件
EventBus.$emit('data-a', message); //事件名,传递参数
}
}
}
</script>
<style scoped>
</style>
组件B
<template>
<div>
<h3>来自组件A的值:{{message}}</h3>
</div>
</template>
<script>
//导入中央事件总线实例
import EventBus from "../eventBus";
export default {
name: "B",
data(){
return{
message:''
}
},
//在mounted中定义接收数据
mounted() { //在模板编译完成后执行
////使用中央事件总线实例对象监听事件
EventBus.$on('data-a',val => {
console.log(val)val
this.message = val;
})
}
}
</script>
<style scoped>
</style>
本文介绍了Vue.js中组件通信的不同方式,包括props与$emit、中央事件总线EventBus等方法,详细展示了如何实现父子组件及非父子组件间的有效数据交互。

被折叠的 条评论
为什么被折叠?



