vue3父子组件同步数据
1.props验证
1.1什么是props验证
指的是:在封装组件时 对外界传递过来的props数据 进行合法性的校验,从而防止数据不合法的问题。
1.2对象类型的props节点
使用对象类型的props节点,可以对每个prop进行 数据类型的校验。
对象类型的props节点提供了多种数据验证方案,例如:
- 基础的类型检查
- 多个可能的类型
- 必填项校验
- 属性默认值
- 自定义验证函数
基础类型的检查:
可以直接为组件的prop属性指定 基础的校验类型,从而防止 组件的使用者 为其绑定 错误类型的数据:
export default {
props: { // 支持的 8 种基础类型
propA: String,
propB: Number,
propC: Boolean,
propD: Array,
propE: Object,
propF: Date,
propG: Function, // 函数类型
propH: Symbol // 符号类型
}
}
多个可能的类型:
如果某个prop属性值的 类型不唯一,此时可以通过数组的形式,为其指定多个可能的类型,示例代码如下:
export default {
props: {
// propA 属性的值可以是 “字符串” 或 “数字”
propA: [String,Number]
}
}
必填项校验:
export default {
props: {
// 通过 “配置对象” 的形式,来定义 propB 属性的 “验证规则”
propB: String, // 当前属性的值必须是 String 字符串类型
required: true // 当前属性的值是必填项,如果使用者没指定 propB 属性的值,则在终端进行警告提示
}
}
属性默认值:
在封装组件时,可以为某个prop属性 指定默认值,实力代码如下:
export default {
props: {
// 通过 “配置对象” 的形式,来定义 propB 属性的 “验证规则”
propC: {
type: Number,
default: 100 // 如果使用者没有指定 propC的值,则 propC属性的默认值为100
}
}
}
自定义验证函数:
在封装组件时,可以为prop属性指定 自定义的验证函数,从而对prop属性的值进行更加精确的控制:
export default {
props: {
// 通过 “配置对象” 的形式,来定义 propB 属性的 “验证规则”
propD: {
// 通过 validator 函数,对 propD 属性的值进行校验,“属性的值”可以通过形参 value 进行接收
validator(value) {
// propD 属性的值,必须匹配下列字符串中的一个
// validator 函数的返回值为 true 表示验证通过,false表示验证失败
return['success','warning','danger'].indexOf(value) !== -1
}
}
}
}
2.计算属性
2.1什么是计算属性
计算属性 本质上 就是一个 function函数,它可以 实时监听 打他钟数据都变化,并 return一个计算后的新值,供组件渲染DOM时使用。
2.2如何声明计算属性
计算属性需要以 function函数 的形式声明到组件的 computed选项中,示例代码如下:
<input type="text" v-model.number="count">
<p>{{ count }} 乘以 2 的值为: {{ plus }}</p>
data() {
return { count:1 }
},
computed: {
plus() { // 计算属性:监听 data 中 count,自动计算出 count * 2 之后的值
return this.count * 2
}
}
**注意:**计算属性 侧重于 得到一个 计算得结果,因此计算属性中 必须有return返回值!
2.3计算属性使用的注意点
- 计算属性 必须定义在computed节点中
- 计算属性 必须是一个function函数
- 计算属性 必须有返回值
- 计算属性 必须当做普通属性使用
2.4计算属性 vs 方法
相对于方法来说,计算属性会缓存计算的结果,只有计算属性的 依赖项发生变化 时,才会 重新进行运算。因此,计算属性的性能更好:
computed: {
plus() { // 计算属性的计算结果会被缓存,性能好
console.log("计算属性被执行啦")
return this.count * 2
}
}
methods: {
plus() { // 方法的计算结果无法被缓存,性能低
console.log("方法被执行啦")
return this.count * 2
}
}
3.自定义事件
3.1什么是自定义事件
在封装组件时,为了让 组件的使用者 可以 监听到组件内状态的变化,此时需要用到 组件的自定义事件。
3.2自定义事件的3个使用步骤
在封装组件时:
- 声明 自定义事件
- 触发 自定义事件
在使用组件时:
3.监听自定义事件
声明自定义事件
开发者为自定义组件封装的自定义事件,必须事先在 emits 节点中声明,示例代码如下:
<template>
<h3>Counter组件</h3>
<button>+1</button>
</template>
<script>
export default {
// my-counter 组件的自定义事件,必须事先声明到 emits节点中
emits: ['change']
}
</script>
触发自定义事件
在 emits 节点下声明的自定义事件,可以通过 this.$emit(‘自定义事件的名称’)方法进行触发,示例代码如下:
<template>
<h3>Counter组件</h3>
<button @click="onBtnClick">+1</button>
</template>
<script>
export default {
// my-counter 组件的自定义事件,必须事先声明到 emits节点中
emits: ['change'],
methods: {
onBtnClick() {
this.$emit('change') // 当点击 +1 按钮时,调用this.$emit()方法,触发自定义的change事件
}
}
}
</script>
监听自定义事件
在使用自定义的组件时,可以通过 v-on 的形式 监听自定义事件。示例代码如下:
<!-- 使用 v-on 指定绑定事件监听 -->
<my-counter @change="getCount"></my-counter>
methods: {
getCount() {
console.log('监听到了 count 值的变化')
}
}
3.3自定义事件传参(子传父)
在调用 this.$emit() 方法触发自定义事件时,可以通过 第2个参数 为自定义事件传参,示例代码如下:
<template>
<h3>Counter组件</h3>
<button @click="onBtnClick">+1</button>
</template>
<script>
export default {
emits: ['change'],
methods: {
onBtnClick() {
this.$emit('change',this.count) // 触发自定义事件时,通过第二个参数传参
}
}
}
</script>
4.组件上的 v-model
4.1为什么需要在组件上使用 v-model
v-model 是双向数据绑定指令,当 需要维护组件内外数据的同步 时,可以在组件上使用v-model指令。
4.2在组件上使用v-model的步骤
父向子同步数据
- 父组件通过v-bind: 属性绑定的形式,把数据传递给子组件
- 子组件中,通过 props 接收父组件传递过来的数据
子向父同步数据
- 在v-bind: 指令之前添加 v-model 指令
- 在子组件中声明 emits 自定义事件,格式为 update:xxx
- 调用 $emit() 触发自定义事件,更新父组件中的数据
子组件:
<template>
<div>
<p>count值是:{{ number }}</p>
<button @click="add">+1</button>
</div>
</template>
<script>
export default {
name: 'MyCounter',
props: ['number'],
emits: ['update:number'],
methods: {
add() {
this.$emit('update:number',this.number + 1)
}
}
}
</script>
父组件:
<template>
<div>
<h1>App根组件 --- {{ count }}</h1>
<my-counter v-model:number="count"></my-counter>
</div>
</template>
<script>
import MyCounter from './Counter.vue'
export default {
name: 'MyCounter',
data() {
return: {
count: 0,
}
}
}
</script>
了解父子组件同步数据特别特别特别重要!!!