vue 已经成为当下最热的前端框架之一,在学生的面试过程中最常问的问题非组件通讯莫属了。
下面我将会详细介绍 vue 当中,组件通讯的几种方式,以及表达技巧。

为什么需要组件通讯?

vue 是组件化开发,我们项目代码中的各个模块都是通过组件组合而成,而且组件之间的参数都会有相互依赖的关系,所以我们需要熟练掌握组件通讯

组件通讯的分类:

  • 父子组件
  • 同级组件
  • 跨域组件

1、父子通讯:

父组件向子组件 Child 传递参数:

  • attr1 静态传参
  • arr2 动态传参
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<Child attr1="msg" :attr2="msg">this is header</Child>
</template>
<script>
import Child from "./child";
export default {
name: 'Header',
data(){
return {
msg:"12323"
}
},
components:{
Child
}
};
</script>

子组件:
子组件通过 props 来获得父组件传递的参数

  • 数组 简单
  • 对象 完整
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<div>这里是子组件</div>
</template>
<script>
export default {
name: 'Child',
// props两种写法
// props:["attr1","attr2"],
props:{
attr1:{
type:"String|Number|Boolean|Null|Undefined|Array|Object|Function",
default:"默认值",
require: true|false
}
}
};
</script>

子父通讯

1
2
子: this.$emit('事件名',"任意数据类型的值")
父:v-on:事件名="回掉函数"

父组件-子组件传递一个函数,子组件调用父组件传递过来的函数,传入参数,父组件传递的这个函数就可以通过回调形参,拿到子组件传递的参数

跨级通讯

  • Vue v2.2 新增 provide/inject

父组件

1
2
3
4
5
6
7
8
9
10
11
12
<template>
<div></div>
</template>

<script>
export default {
provide:{
key:val,
...
}
};
</script>

子组件

1
2
3
4
5
6
7
8
9
10
<template>
<div></div>
</template>

<script>
export default {
name: "DialogFooot",
inject:["key1",...],
};
</script>
  • Vue v2.4 新增 $attrs

想要使用$attrs 在父组件中不可以通过 props 去定义
祖先组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<div>
<Parent :key1="key1" :key2="key2" ...></Parent>
</div>
</template>

<script>
export default {
name: "Origine",
data(){
return {
key1:val1,
key2:val2
}
}
};
</script>

父组件 - Parent:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<div>
// 父组件可以通过$attrs获得祖先组件中的数据
// 不需要通过props去接受
{{$attrs}}
<Child v-bind="$attr"></Child>
</div>
</template>

<script>
export default {
name: "Parent",
inheritAttrs: false,
};
</script>

子组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<div>
// 子组件需要获得父组件的参数,父组件通过v-bind将$attr绑定
{{$attrs}}
</div>
</template>

<script>
export default {
name: "Child",
inheritAttrs: false,
mounted(){
// js方式
console.log(this.$attrs)
}
};
</script>

EventHub & EventBus

由于 vue 原生支持发布、订阅模式,我们通过 new Vue() 创建新的实例。
utils/hub.js

1
2
import Vue from "vue";
export default new Vue();

main.js

1
2
3
4
5
6
7
8
9
10
11
12
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
Vue.config.productionTip = false;
import EventHub form "@/utils/events"

Vue.prototype.$eventHub = EventHub;

new Vue({
router,
render: h => h(App),
}).$mount("#app");
1
2
3
组件内部:
子:this.$eventhub.emit('eventname',callback);
父:this.$eventhub.$on('event',callback)

Vuex