1、什么是组件通信
组件通信就是指组件与组件之间的数据传递。因为组件的数据是独立的,无法直接访问其他组件的数据,想获取其他组件的数据,就需要用到组件通信。
2、组件关系分类(如图)
● 父子关系(props 和 $emit )
● 非父子关系(provide & inject;eventbus)
通用解决方案:Vuex--适合于复杂业务场景
3、父组件向子组件传递数据
父组件利用props向子组件传递数据
① 父中给子添加属性传值 ② 子props 接收 ③ 子组件使用
// 父组件
<template>
<div class="main">
<!-- 1、给子组件以自定义属性方式传值,btnName为自定义属性 -->
<my-button :btnName="name"></my-button>
</div>
</template>
<script>
import myButton from "./myButton.vue";
export default {
data() {
return {
name: "父组件传值",
};
},
components: { myButton },
};
</script>
// 子组件
<template>
<div>
<!-- 2、子组件模板中直接使用 -->
<button>{{ btnName }}</button>
</div>
</template>
<script>
export default {
data() {
return {};
},
// 2、子组件内部通过props接收
props: {
btnName: String,
},
};
</script>
结果如下--按钮名称为“父组件传值”:
4、子组件向父组件传递数据
子组件利用$emit 通知父组件,对数据进行更新
① 子$emit 发送消息 ②父中给子添加消息监听 ③ 父中实现处理函数
// 子组件
<template>
<div>
<button @click="changBtnName">{{ btnName }}</button>
</div>
</template>
<script>
export default {
data() {
return {};
},
props: {
btnName: String,
},
methods: {
changBtnName() {
// 1、$emit 触发事件,给父组件发送消息通知
this.$emit("changBtnName", "修改名称");
},
},
};
</script>
// 父组件
<template>
<div class="main">
<!-- 2、父组件监听事件 -->
<my-button :btnName="name" @changBtnName="handleChange"></my-button>
</div>
</template>
<script>
import myButton from "./myButton.vue";
export default {
data() {
return {
name: "父组件传值",
};
},
components: { myButton },
methods: {
handleChange(val) {
// 3、提供处理参数,此处的形参(val)代表子组件传递过来的参数
this.name = val;
},
},
};
</script>
结果如下--点击子组件的按钮后,名称更新为“修改名称”
5、父子组件之间传值还可使用 ref & refs
详见以下链接:VUE--- ref & refs-CSDN博客
扩展:
1、什么是prop
● 定义:组件上注册的一些自定义属性
● 作用:向子组件传递数据
● 特点:可以传递任意数量、任意类型的prop
2、prop校验
作用:为组件的prop指定验证要求,不符合要求的,控制台就会有错误提示,帮助开发者快速发现错误。
类型:
a、类型校验
b、非空校验
c、默认值校验
d、自定义校验
prop: {
校验的属性名: {
type: 类型, // Number, Boolean, Object, String ...
required: true, // 表示父组件必须传递这个值
default: 默认值, // 默认值如果是数组或对象,要写成函数格式,函数中返回数组或对象
validator(value) {
// 自定义校验规则
return 是否通过校验
}
}
}
3、prop & data 的区别
● data的数据是自己的,可以随便修改
● prop的数据是外部的,不能直接修改,要遵循单项数据流
4、单向数据流
父级prop的数据更新,会向下流动,影响子组件。这个数据流动是单向的,无法反向流动。