1. 前言
组件化是Vue.js最突出的特征之一。Vue组件化为我们提供了一种抽象,让我们可以通过使用独立的可复用的组件来构建大型应用。而如何快速有效地实现组件间的通信,是我们在开发过程中经常会碰到以及使用到的技巧。这里我给大家介绍一下Vue组件间通信的几种方式。
2. 组件通信常用方式
-
props
-
$emit
-
bus 事件总线
-
vuex
-
$refs、$parent、$children
3. 组件通信具体实现
1. 父给子传值
使用props
//parent
<child :msg="message"></child>
//child
<script>
export default{
props:['msg']
//props:{ msg:String }
}
</script>
- 扩展:使用sync修饰符,修改props中数据
//parent
<child :msg.sync="message"></child>
//child
this.$emit('update:msg', this.changeValue);
2. 子给父传值
使用$emit
//child
this.$emit('toParent', this.msg);
//parent
<child @toParent="getChildMsg"></child>
3. 兄弟间传值
-
结合使用props和$emit实现
//child1 子传给父 this.$emit('toParent', this.msg); //child2 接收父传过来的值 export default { props: ['msg'] }; //parent 接收child1传过来的值 并传递给child2 <child1 @toParent="getChildMsg"></child1> <child2 :msg="msg"></child2> methods: { getChildMsg(msg) { this.msg = msg; } }
-
通过$parent注册和监听事件
//child1 子通过$emit注册事件 methods: { sendMessage() { this.$parent.$emit('foo', this.msg); } } //child2 子通过$on监听事件 mounted() { this.$parent.$on('foo', msg => { console.log(msg); }); } //parent <button style="100px;height:30px" @click="sendMessage"> sendMessage </button> methods: { sendMessage() { this.$refs.child1.sendMessage(); } }
4. 祖先和后代间传值
-
使用provide/inject
// 祖先通过provide传值 provide() { return { msg: '来自祖先的消息' } }, //后代通过inject接收值 类似于props的方式 inject: ['msg']
-
使用
$attrs
和$listeners
- 需要在父组件中使用v-bind="$attrs" v-on="$listeners"。$attrs用于调用祖辈非props接收的参数,$listeners用于调用祖辈方法
-
index.vue(祖先)
<template> <div> <comp-a :name="name" :age="age" :phone="phone" @study="study"> </comp-a> </div> </template> <script> import CompA from './CompA.vue'; export default { components: { CompA }, data() { return { name: 'jack', age: 18, phone: 'iphone' }; }, methods: { study(parmas) { console.log('study'); } } }; </script>
-
compA.vue(parent)
<template> <div> <comp-b v-bind="$attrs" v-on="$listeners"></comp-b> </div> </template> <script> import CompB from './CompB.vue'; export default { components: { CompB }, props: { name: { type: String, default: '' }, age: { type: Number, default: 0 } }, mounted() { console.log('compA'); console.log('attrs', this.$attrs); this.$listeners.study('compA'); } }; </script>
-
compB.vue(child)
<template> <div> </div> </template> <script> export default { mounted() { console.log('compB'); console.log('attrs', this.$attrs); console.log('this', this); // 调用祖先方法 this.$listeners.study('compB'); } }; </script>
console.log打印结果: