Vue组件之间的通信

本文介绍了Vue.js中组件通信的不同方式,包括props与$emit、中央事件总线EventBus等方法,详细展示了如何实现父子组件及非父子组件间的有效数据交互。

组件是 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>

3、Vuex通信

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值