Vue组件之间通信

Vue

一、组件

二、组件之间的通信

组件实例之间的作用域是孤立的, 这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。

2.1父子组件通信

2.1.1、父组件与子组件通信使用props属性进行传递

1
2
3
4
5
6
7
8
9
10
11
// 声明一个子组件
Vue.component('child', {
props: ['msg'],
template: '<span>{{msg}}</span>'
})

// 调用子组件
<child msg="hello!"></child>

// 最终结果
hello!

2.1.2、子组件与父组件通信,利用自定义事件去传递

$on、$emit

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
<div id="root">
<p>{{total}}</p>
<button-count @update="update"></button-count>
</div>
Vue.component('button-count', {
/*
data参数必须是一个函数,返回的是一个全新的对象,保证组件在重复调
用的时候都能保证有自己的内部状态; 如果将data直接写成一个对象,那么
Vue会停止运行并发出警告
*/
data() {
return {
count: 0
}
}
template: '<span @click="update">{{count}}</span>',
methods: {
update() {
this.count ++
this.$emit('update', this.count)
}
}
})

new Vue({
el: '#root'
data: {
total: 0
},
methods: {
update(val) {
this.total = val
}
}
})

2.2非父子组件通信

非父子组件通信问题Vue框架本身是没有根本解决的,简单场景下,可以设置全局事件中心去解决即使用一个空的Vue实例作为事件总线

创建一个bus.js 文件

1
export const bus = new Vue()

引入全局bus

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
import { bus } from './bus.js'

// A组件
new Vue({
methods: {
handle() {
bus.$on('attach', (msg) => {
console.log(msg)
})
}
}
})

// B组件
import { bus } from './bus.js'
new Vue({
data() {
return {
msg: 'hello!'
}
}
created() {
bus.$emit('attach', this.msg)
}
})

总结: 组件通信有几种情况

三、简单拓展

3.1、自定义事件的表单输入

v-model是Vue实现双向数据绑定最常用的一种语法糖,其实相当于使用了自定义事件去实现的

1
2
3
4
<input v-model="val">

// 相当于
<custom-input :value="val" @input="something = arguments[0]">

即想实现双向数据绑定必须满足:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// v-model语法糖简单示例
Vue.component('current-input', {

template: '<input :value="value" @input="update($event.target.value)">',

data() {
return {
value: 0
}
},

methods: {
update(val) {
this.value = val
}
}
})

3.2、.sync修饰符

这个修饰符也算是一个语法糖,可以在父子组件通信的时候,不需要再父组件内显示去监听函数来更新父组件内相应状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 在父组件中调用Upload组件
<Upload :img.sync="images">
new Vue({
data() {
return {
images: []
}
}
})
Vue.component('Upload', {
template: '<div><button @click="upload"></button></div>',
data() {
return {
img: []
}
},
methods: {
upload() {
this.img = ['./img1.jpg']
this.$emit('upload:img', this.img)
}
}
})