组件的通信方式有多种,比如父子通信,隔代通信等,不同的组件通信方式所用到的技术还不同,下面我会从父子通信,和隔代通信给大家介绍接种通信方式
父子通信
首先第一种就是父子通信,在一个组件内引入并注册使用了另一个组件,这就构成了父子组件的关系。
父子通信使用的是props和$emit关键字,这是一种比较完善的组件之间的通信方式
具体使用方式如下:
父传子props:
1.父组件中给子组件添加属性传值
2.子组件使用props接收
3.子组件使用接收到的值
子传父$emit$(this.$emit( ' 事件名 ',要传递的数据 ))
1.字组件$emit发送消息
2.父组件在子组件上添加消息监听
3.父组件在监听到消息处理函数
非父子通信(隔代通信)
非父子通信的方式有很多种,事件总线,project&inject 还有vuex下面主要讲解前两种,vuex我会单独出一篇文章。感兴趣的朋友可以关注一下。
事件总线
event bus事件总线作用就是非父子组件中进行简单的消息传递
下面是使用enent bus的步骤:
1.创建一个都能访问的事件总线(utils/EventBus.js)
// 在utils/EventBus.js中
import Vue from 'vue'
const Bus = new Vue()
export default Bus
2.A组件(接收方),监听Bus事件实例
//在EventBus.js中创建事件总线的时候
// 在A组件需要导入事件总线
import Bus from '@/utils/EventBus';
created(){
Bus.$on('sendMsg',(msg) => {
this.msg = msg
})
}
3.B组件(发送方),触发Bus事件实例
// 假设B组件在点击按钮的时候触发了sedMsg事件
methods:{
senMsg(){
Bus.$emit('senMsg','我是传递过来的数据')
}
}
注意:事件总线传递的数据不是响应式的,因为事件总线本质是一个普通的JavaScript对象,并不是Vue组件或实例对象,因此它无法像Vue组件那样自动的实现响应式更新
project&inject
作用:跨层级共享数据
简单类型数据:非响应式
复杂数据类型:响应式
(传递复杂类型的数据会设计到引用数据类型和简单数据类型在内存中的存储知识,会涉及到栈和堆以及内存,有兴趣的小伙伴可以自己研究一下,或者留言)
使用步骤:
1.父组件provide提供数据(如果想要修改父组件中的数据,父组件需要传递一个函数)
export default{
provide(){
return{
数据...
}
}
}
2.子/孙inject取值
export default{
inject:['数据1','数据2']
}
组件中传值的另一种方式:
前置知识点:
inheritAttrs决定属性是否设置到组件的根节点上 false表示不设置,true表示设置
$attrs父组件在使用子组件的时候,咋子组件标签上使用了没有在组件中设置props的属性
in 判断对象中是否存在一个key
下面是vue2官方文档里面的解释:
也就是说 在父组件中使用的子组件上设置了属性,会默认作用到子组件的根节点上,而$attrs又可以拿到子组件中没有通过props接受的父组件传递过来的值,那么我们可以用这个知识点做一些事情了。
下面是一段封装vant-file的组件
父组件
<template>
<div>
<field
label="密码"
placeholder="请输入用户名"
type="password"
v-model="value"
disabled
>
</field>
</div>
</template>
<script>
import field from '@/components/flied.vue'
export default {
components: {
field
},
data() {
return {
value: ''
}
}
}
</script>
<style></style>
子组件:
<template>
<label for="">
<!--
inheritAttrs决定属性是否设置到组件的根节点 false不设置,true设置
$attrs父组件在使用子组件的时候,在子组件标签上使用了没有在子组件中设置props的数字属性
in 判断对象中是否存在一个key
-->
<input
:type="type"
:placeholder="placeholder"
:disabled="isDisabled"
:readonly="isReadonly"
@input="$emit('input', $event.target.value)"
/>
</label>
<!-- <input type="text"> -->
</template>
<script>
export default {
inherAttrs: false,
props: {
label: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '我是提示的内容'
},
type: {
type: String,
default: 'text'
},
value: {
type: String,
default: ''
}
},
// props: ['label', 'placeholder', 'type'],
data() {
return {
height: '80px',
pl: this.placeholder,
isDisabled: false,
isReadonly: false
}
},
created() {
console.log(this.type, this.placeholder, this.label)
console.log(this.$attrs)
if ('disabled' in this.$attrs) {
this.isDisabled = true
}
if ('readonly' in this.$attrs) {
this.isReadonly = true
}
}
}
</script>
<style></style>
在子组件通过props接收了父组件传递过来的label,placeholder,type和 value,但是没有接收父组件传递的disabled属性,那么在created钩子函数中的this.$attrs中就保存了disabled这个属性
不妨打印一下看看
如果我在父组件在传递一个readonly属性,组件还是没有通过props接收,那么this.attrs保存的结果就是这样的
这样我们就可以通过this.attrs这个对象进行一些操作,如果我们没有在子组件中使用props接收,那么也可以使用this.$attrs这个属性拿到父组件传递过来的值。
本次分享到这就结束了,如果有写错的地方欢迎大家进行指正,有喜欢前端的伙伴可以在评论中一起讨论问题。