vue中父子组件通信的方式

props / $emit

最经典&使用最多的通信方式,父组件通过props的方式向子组件传递数据,子组件通过$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
36
37
38
39
40
41
42
43
44
45
46
47
// 父组件
<template>
<div id="app">
<HelloWorld :msg='msg' @onChangeFatherMsg='onChangeFatherMsg' />
</div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
data() {
return {
msg: "Welcome to Your Vue.js App",
};
},
components: {
HelloWorld,
},
methods: {
onChangeFatherMsg(e) {
this.msg = e;
},
},
};
</script>

// 子组件
<template>
<div class="hello">
<h1 @click="changeFatherMsg">{{ msg }}</h1>
</div>
</template>

<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
methods: {
changeFatherMsg() {
this.$emit("onChangeFatherMsg", "hello world");
},
},
};
</script>

$children / $parent(vue 3.x已移除)

要注意边界情况,如在#app上拿$parent得到的是new Vue()的实例,在这实例上再拿$parent得到的是undefined,而在最底层的子组件拿$children是个空数组。也要注意得到$parent和$children的值不一样,$children 的值是数组,而$parent是个对象

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
// 父组件
<template>
<div id="app">
<button @click="changeChildren">改变子组件值</button>
<HelloWorld />
</div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
name: "App",
data() {
return {
fatherMsg: "hello",
};
},
components: {
HelloWorld,
},
methods: {
changeChildren() {
this.$children[0].privateMsg = "嘿嘿嘿";
},
},
};
</script>

// 子组件
<template>
<div class="hello">
<h1>{{ privateMsg }}</h1>
</div>
</template>

<script>
export default {
name: "HelloWorld",
data() {
return {
privateMsg: "子组件",
};
},
mounted() {
console.log(this.$parent.fatherMsg);
},
};
</script>

provide/ inject

provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

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
// 父组件
<template>
<div id="app">
<HelloWorld />
</div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
name: "App",
provide: {
for: "子组件",
},
components: {
HelloWorld,
},
};
</script>

// 子组件
<template>
<div class="hello">
<h1>{{ privateMsg }}</h1>
</div>
</template>

<script>
export default {
name: "HelloWorld",
inject: ["for"],
data() {
return {
privateMsg: this.for,
};
}
};
</script>

$refs

ref如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 父组件
<template>
<div id="app">
<HelloWorld ref="helloworld"/>
</div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
name: "App",
components: {
HelloWorld,
},
mounted(){
console.log(this.$refs.helloworld.privateMsg)
}
};
</script>

// 子组件同上

eventBus

EventBus是消息传递的一种方式,基于一个消息中心,订阅和发布消息的模式,称为发布订阅者模式。(eventBus原理)

on(‘name’, fn)订阅消息,name:订阅的消息名称, fn: 订阅的消息
emit(‘name’, args)发布消息, name:发布的消息名称 , args:发布的消息

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
// 在App.vue同级目录创建文件exentBus.js
import Vue from 'vue'
export const EventBus = new Vue();

// 同级组件A,发布
<template>
<div class="hello">
<h1 @click="componentAEvent">{{ num }}</h1>
</div>
</template>

<script>
import { EventBus } from "../exentBus";
export default {
name: "HelloWorld",
data() {
return {
num: 1,
};
},
methods: {
componentAEvent() {
EventBus.$emit("add", {
num: this.num++,
});
},
},
};
</script>

// 同级组件B,订阅
<template>
<div class="hello">
<h1>{{ count }}</h1>
</div>
</template>

<script>
import { EventBus } from "../exentBus";

export default {
name: "HelloWorld",
data() {
return {
count: 0,
};
},
mounted() {
EventBus.$on("add", (params) => {
this.count = params.num;
});
},
};
</script>

$attrs与 $listeners(vue 3.x 移除了$listeners)

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
// 父组件
<template>
<div id="app">
<HelloWorld name='name' age='18' gender='男' />
</div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
name: "App",
components: {
HelloWorld,
},
};
</script>

// 子组件
<template>
<div class="hello">
<h1>{{ num }}</h1>
</div>
</template>

<script>
export default {
name: "HelloWorld",
data() {
return {
num: 1,
};
},
inheritAttrs: false, // false是this.$attrs为{age: "18", gender: "男"}
props: {
name,
},
mounted() {
console.log(this.$attrs); // inheritAttrs为true时的输出 {name: "name", age: "18", gender: "男"}
},
};
</script>

vue中父子组件通信的方式
https://xypecho.github.io/2021/03/23/vue中父子组件通信的方式/
作者
很青的青蛙
发布于
2021年3月23日
许可协议