1. vue组件通信的方式
- prop(父传子)
- $emit(子传父)
- $attrs 和 $listeners
- provide 和 inject
- EventBus(事件总线)
1.1 prop
用于父组件向子组件传递数据
父组件
<template>
<div class="data-analysis">
// 父组件通过自定义属性userBehaviorList将userBehaviorList传递给子组件
<dataAnalysisSelect :userBehaviorList="userBehaviorList" :sceneObj="item.sceneList[0]">
</dataAnalysisSelect>
</div>
</template>
子组件
<template>
<div style="display:flex;margin-top:1px">
<Select v-model="innerValue.sceneType" style="margin:0 10px;width:220px" @on-change="changeType">
<Option :value="it.strValue" v-for="it in userBehaviorList" :key="it.value">{{ it.name }}</Option>
</Select>
<Select v-model="innerValue.sceneKey" style="margin:0 10px;width: 220px" filterable @on-change="changeSceneKey">
<Option :value="it.rkey" v-for="(it,index) in sceneKeyList" :key="it.index">{{ it.name }}</Option>
</Select>
</div>
</template>
export default {
props: {
//接收userBehaviorList数组
userBehaviorList: {
type: Array,
default() {
return []
}
},
sceneObj: {
type: Object,
default() {
return {}
}
}
},
}
1.2 $emit
父组件自定义事件,子组件主动触发事件并传递数据
父组件
<template>
<div>
//父组件自定义事件`@radioChange="radioChange"`
<Radio v-else-if="formItem.value==4" :formId="formItem.id" v-model="list[formItem.strValue]" :strValue="formItem.strValue" :userList="currentUser" @radioChange="radioChange"></Radio>
</div>
</template>
子组件
<template>
<RadioGroup v-model="innerValue" @on-change="changeValue">
<Radio :label="item.value" v-for="item in radioList" :key="item.id">{{item.name}}</Radio>
</RadioGroup>
</template>
export default {
model:{
event:'changeRadioValue',
prop:'innerValue'
},
methods:{
changeValue(){
//子组件通过$emit触发父组件的自定义事件,将所需要传递到数据传给父组件
this.$emit('radioChange',this.strValue,this.radioList[i].name,this.obj)
}
},
}
1.3 attrs 和 listeners
- $attrs
包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=“$attrs” 传入内部组件——在创建高级别的组件时非常有用
- $listeners
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=“$listeners” 传入内部组件——在创建更高层次的组件时非常有用。
3.attr负责存储属性,listeners负责存储事件,都是以对象的形式存储数据
父组件
<template>
<div class="home">
<Child :first="first" :second="second" @getFirst.native="getFirst" @getSecond="getSecond"></Child>
</div>
</template>
export default {
components:{Child},
data(){
return {
first:1,
second:2,
}
},
methods:{
getFirst(){
console.log(this.first)
},
getSecond(){
console.log(this.second)
}
},
}
子组件
<template>
<div>
// 1
<h2>{{first}}</h2>
</div>
</template>
export default {
props:{
first:{
type:Number,
default:0
}
},
created(){
console.log(this.$attrs,this.$listeners)
// {second:2} {getSecond:fn}
this.$listeners.getSecond() // 2
}
};
1.4 provide和inject
相互配合使用,缺一不可
祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。
祖先组件
<template>
<div class="home">
<Son></Son>
</div>
</template>
export default {
components:{Son},
provide:{
house:'房子',
car:'车',
money:'钱'
}
};
子孙组件
<template>
<div>
</div>
</template>
<script>
export default {
inject:{
house:{
default:'没房'
},
car:{
default:'没车'
},
money:{
default:'没钱'
}
},
created(){
console.log(this.house,this.car,this.money)
//没房,没车,没钱
}
};
</script>
1.5 EventBus
声明一个全局Vue实例变量EventBus,把所有的通信数据,事件监听都存储到这个变量上,这样就到达在组件间实现数据共享,有点类似Vuex。但是这种方式只适合极小的项目,复杂的项目还是推荐Vuex。
父组件
<template>
<div class="home">
<EventBus></EventBus>
</div>
</template>
Vue.prototype.EventBus = new Vue()
export default {
components:{EventBus},
created(){
this.EventBus.message = '事件总线';
this.EventBus.$on('received',function(params){
console.log(params) //子组件
})
this.$nextTick(()=>{
console.log(this.EventBus.child) // child
})
},
};
子组件
export default {
created(){
console.log(this.EventBus.message) // 事件总线
this.EventBus.$emit('received','子组件')
this.EventBus.child = 'child'
}
};