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组件间的通讯。
完~