vue2.0以后,events 选项被弃用。原来用于父子组建间的通讯的\$dispatch 和 \$broadcast 也已经被弃用。取而代之的是可以通过单独的事件中心管理组件间的通信。
父子组件间的通讯
这些方法的最常见用途之一是父子组件的相互通信。在这些情况下,你可以使用 v-on监听子组件上 $emit 的变化。这可以允许你很方便的添加事件显性。例如:
在goods组建中,包含了两个子组件cartcontrol.vue和shopcart.vue。cartcontrol.vue中点击,传递当前点击的元素到shopcart.vue中,则可以这样做:
在cartcontrol.vue组件中通过addCart事件触发$emit提交事件’cart-add’1
2
3addCart(event) {
  this.$emit('cart-add', event.target);
}
goods.vue组件中调用cartcontrol.vue组件上使用v-on来监听$emit的变化1
2
3<div class="cartcontrol-wrapper">
  <cartcontrol v-on:cart-add="cartAdd"></cartcontrol>
</div>
如果$emit有变化(这里是点击)则触发goods组件下的cartAdd(target)方法。1
2
3cartAdd(target) {
	this.$refs.shopcart.drop(target);
}
v-el 2.0中已经废弃全部采用ref和\$refs,这里通过给shopcart.vue组件属性ref=”shopcart”,利用this.\$refs.shopcart访问shopcart.vue组件中的drop(target)方法。1
<shopcart ref="shopcart"></shopcart>
这样在shopcart.vue组件中的drop(el)方法就可以访问cartcontrol.vue组件点击的dom元素。1
2
3drop(el) {
	console.log(el);
}
这个例子的全部逻辑是:从子组件cartcontrol传点击的dom对象到父组件goods,然后通过父组件通过ref属性,调用子组件的方法,从而把当前的dom对象再传到另一个子组件shopcart中。
单一事件中心管理组件通信(可跨多层父子组件通信)
举个例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 //准备一个空的实例对象
var Event=new Vue();
var A={
    template:`
        <div>
            <span>我是A组件</span> -> {{a}}
            <input type="button" value="把A数据给C" @click="send">
        </div>
    `,
    methods:{
        send(){
            Event.$emit('a-msg',this.a);
        }
    },
    data(){
        return {
            a:'我是a数据'
        }
    }
};
var B={
    template:`
        <div>
            <span>我是B组件</span> -> {{a}}
            <input type="button" value="把B数据给C" @click="send">
        </div>
    `,
    methods:{
        send(){
            Event.$emit('b-msg',this.a);
        }
    },
    data(){
        return {
            a:'我是b数据'
        }
    }
};
var C={
    template:`
        <div>
            <h3>我是C组件</h3>
            <span>接收过来的A的数据为: {{a}}</span>
            <br>
            <span>接收过来的B的数据为: {{b}}</span>
        </div>
    `,
    data(){
        return {
            a:'',
            b:''
        }
    },
    mounted(){
        //var _this=this;
        //接收A组件的数据
        Event.$on('a-msg',function(a){
            this.a=a;
        }.bind(this));
        //接收B组件的数据
        Event.$on('b-msg',function(a){
            this.b=a;
        }.bind(this));
    }
};
window.onload=function(){
    new Vue({
        el:'#box',
        components:{
            'com-a':A,
            'com-b':B,
            'com-c':C
        }
    });
};
如上,通过一个空的Vue对象Event,来集中管理组件件的通讯,这就是单一事件中心管理组件通信。
前面父子组件间的通讯的例子,通过单一事件中心管理可以这样实现:
新建 components/event-bus.js1
2import Vue from 'vue';
export var eventBus = new Vue();
在组件 shopcart 里 created 方法里定义事件1
2
3
4
5
6
7
8import { eventBus } from 'components/event-bus';
 // ...
  created() {
    eventBus.$on('addcart', (ele) => {
      console.log(ele);
    });
  },
  // ...
cartcontrol 组件内触发事件1
2
3
4
5
6
7
8
9import { eventBus } from 'components/event-bus';
// ...
methods: {
  addToCart(e) {
    // ...
    eventBus.$emit('addcart', e.target);
  }
}
// ...
在Vue的官网是这样说明单一事件中心管理组件通信:
如果是跨多层父子组件通信的话,$emit 并没有什么用。相反,用集中式的事件中间件(即单一事件中心管理组件)可以做到简单的升级。这会让组件之间的通信非常顺利,即使是兄弟组件。因为 Vue 通过事件发射器接口执行实例,实际上你可以使用一个空的 Vue 实例。
比如,假设我们有个 todo 的应用结构如下:1
2
3
4Todos
├─ NewTodoInput
└─ Todo
   └─ DeleteTodoButton
可以通过单独的事件中心管理组件间的通信:1
2
3// 将在各处使用该事件中心
// 组件通过它来通信
var eventHub = new Vue()
然后在组件中,可以使用 $emit, $on, $off 分别来分发、监听、取消监听事件:1
2
3
4
5
6
7
8// NewTodoInput
// ...
methods: {
  addTodo: function () {
    eventHub.$emit('add-todo', { text: this.newTodoText })
    this.newTodoText = ''
  }
}
| 1 | // DeleteTodoButton | 
| 1 | // Todos | 
在简单的情况下这样做可以替代\ $dispatch 和 \$broadcast,但是对于大多数复杂情况,更推荐使用一个专用的状态管理层如:Vuex。
以上就是vue组件间的通讯。
完~