组件
Vue组件之间的关系大致可以分为父子组件和非父子组件,非父子组件又可以分成兄弟组件和跨级组件。
通信方式
vue中的通信方式分为以下7种
- prop/$emit
- v-slot:(单向),实现可复用组件,传Dom、html等可以考虑
- $refs/$parent/$children/$root
- $attrs/$listener (双向跨级)
- provide/inject
- eventBus (存在内存泄漏问题)
- Vuex (全局通信)
不同的通信方式适用于不同关系的组件之间
- 父子组件间通信:1,2,3,4,5,6,7(果然还得是父子组件)
- 兄弟组件:6,7
- 跨级组件:4,5,6,7
prop/$emit
prop/$emit可以说是父子组件间通信用得最多的了。
-
父组件 -> 子组件:通过prop
父组件引入子组件并传入参数
<my-child :title="title" ><my-child>子组件接收prop
props:{ title:{ type:String, default:'标题', } } -
子组件 -> 父组件:$emit
子组件通过$emit向上传参数
<button @click="emitData">向父组件传参</button>emitData(){ this.$emit('fromChild','子组件传的参数') }父组件接收子组件传来的参数
<my-child :title="title" @fromChild="receive"><my-child>receive(data){ console.log(data) }
v-slot
插槽又分为具名插槽和默认插槽
默认插槽
//父组件
<my-child :title="title" @fromChild="receive">
<div>默认插槽</div>
<my-child>
//子组件
<div>
...
<slot></slot>
...
</div>
具名插槽
注:具名插槽需要包在template里面,要不然会报错
//父组件
<my-child>
<template v-slot:mySlot> // v-slot: + 插槽名
···
</template>
</my-child>
//子组件
<div>
<slot name="mySlot"></slot> // name="插槽名"
</div>
以具名插槽为例v-slot传参
//父组件
<testChild>
<template v-slot:mySlot="slotData">//具名插槽,v-slot: +插槽名+ ="自定义数据名",子组件所传参数都是其属性
{{slotData.name}}
</template>
</testChild>
//子组件
<div>
...
<slot name="test" :name="name"></slot>
...
</div>
$refs/$parent/$children/$root
$refs:可以将$refs绑定在子组件上,从而获取子组件的实例。
$parens :直接通过this.$parent来获取当前组件的父组件实例。
$children : 同样也可以直接通过this.$children来获取当前组件的子组件实例。
注意:this.$children数组中的元素下标并不一定对用父组件引用的子组件的顺序。所以在使用时需要根据一定的条件例如子组件的name去找相应的子组件。
$root: 当前组件树的根Vue实例。如果当前实例没有父实例,此实例就是自己。通过$root,可以实现组件之间的跨级通信。
$attrs/$listener
$attrs可以获取父组件传递过来的所有属性,不包含class,style和props中接收的
当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ,并且可以通过 v-bind="$attrs" 传入内部组件,在创建高级别的组件时非常有用
使用$attrs的好处
- 在子组件中不用再通过props来接收来自父组件的信息
- 在子组件中调用孙子组件,绑定$attrs,孙子组件就可以直接接收父组件的内容
- 多层传递省时省力
$listeners,它是一个对象,里面包含了作用在这个组件上的所有监听器。
$listeners的作用很明显,就是在高层组件向低层组件传参使用$attrs一样,低层组件向高层组件传递数据用$listeners即可。解构后,和正常函数一样调用。
provide/inject
provide/inject使用方法很简单,父组件(或者说高层组件)通过provide提供数据,其他组价可以使用inject注入数据。
平时开发并不推荐使用provide/inject,开发组件库,插件库除外,写的位置与data同级
//父组件
provide() {
return {
parent: "这是父组件的provide"
};
}
//子组件
inject:
{
parent: {
default: () => ({})
}
},
eventBus
有时候关系复杂的组件之间需要通信,那么之前提到的方法就会变得很复杂,所以就需要有个事件总线来进行通信(就很像接线员把需要通信的双方连接起来)
可以定义一个全局的eventBus,当然如果用得不多也可以定义eventBus然后局部引用,这里以全局为例
//main.js
window.eventBus = new Vue(); //可以挂在window下也可以挂在Vue.prototype下
//触发事件
EventBus.$emit('eventName', param1,param2,...)
//监听事件
EventBus.$on('eventName', (param1,param2,...)=>{
...
})
//移除事件
EventBus.$off('eventName');
注:页面销毁的时候请养成移除事件的好习惯
Vuex
Vuex若要详细说可能会有很多内容,那就放在下次的文章里单独说