在Vue中,组件之间数据传递可以使用props进行传递。
数据传递
示例1
App.vue
<template>
<div>
<Child :cData="childData"></Child>
</div>
</template>
<script>
import Child from './Child.vue';
export default {
components: {
Child
},
data() {
return {
childData: {
name: "Guo",
age: 37,
gender: 'M'
}
}
}
}
</script>
Child.vue
<template>
<div>
Child components ---
{{ }} - {{ cData.age }} -{{ cData.gender }}
</div>
</template>
<script>
export default{
props:['cData']
}
</script>
显示结果:
在上述示例中,App.vue调用Child.vue中的组件Child,并将属性 cData传递给Child,同时Child.vue通过props进行接受,直接使用数组形式。
这种方式是最简单的形式。
数据校验
还可以通过一些属性对props中的数据进行校验,做常见的有 require default type 以及validator
以下为数据校验的示例:
示例2
App.vue
<template>
<div>
<button @click="handleShow">show/hide</button>
<button @click="handleLevel">level+1</button>
<Child :cData="childData" :dataShow="dataShow" :level="level"></Child>
</div>
</template>
<script>
import Child from './Child.vue';
export default {
components: {
Child
},
data() {
return {
childData: {
name: "Guo",
age: 37,
gender: 'M'
},
dataShow:true,
level:0
}
},
methods:{
handleShow(){
this.dataShow = !this.dataShow
},
handleLevel(){
this.level++
}
}
}
</script>
Child.vue
<template>
<div v-show="dataShow">
Child components ---
{{ }} - {{ cData.age }} - {{ cData.gender }} -{{ level }}
</div>
</template>
<script>
export default{
props:{
cData:{
type: Object
},
dataShow:{
type: Boolean,
defualt: true
},
level:{
type: Number,
required: true,
validator(value){
return [0,1,2,3,4].includes(value)
}
}
}
}
</script>
显示结果
在这段代码中,父组件添加了两个按钮来改变传递给子组件的值dataShow level。在子组件中对props中的数据进行了一定的校验限制:cData类型为Object ;dataShow类型为Boolean,默认为true;level为必选,Number类型,数据限定在0,1,2,3,4
如图中所示,当点击level+1按钮,level不在属于0,1,2,3,4后控制台会有相应的报错。
数据流向
所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。
依旧以上文示例为例,
示例3
App.vue
<template>
<div>
<button @click="handleShow">show/hide</button>
<button @click="handleLevel">level+1</button>
<Child :cData="childData" :dataShow="dataShow" :level="level"></Child>
</div>
</template>
<script>
import Child from './Child.vue';
export default {
components: {
Child
},
data() {
return {
childData: {
name: "Guo",
age: 37,
gender: 'M'
},
dataShow:true,
level:0
}
},
methods:{
handleShow(){
this.dataShow = !this.dataShow
},
handleLevel(){
this.level++
}
}
}
</script>
Child.vue
<template>
<div v-show="dataShow">
<button @click="handleLevel">level-1</button>
Child components ---
{{ }} - {{ cData.age }} - {{ cData.gender }} -{{ level }}
</div>
</template>
<script>
export default{
props:{
cData:{
type: Object
},
dataShow:{
type: Boolean,
defualt: true
},
level:{
type: Number,
required: true,
validator(value){
return [0,1,2,3,4].includes(value)
}
}
},
methods:{
handleLevel(){
this.level++
}
}
}
</script>
改动为在Child.vue中添加一个按钮,用来减少leve。可以看到控制台中直接有错误,不允许修改。
一些补充细节
- 所有 prop 默认都是可选的,除非声明了 required: true。
- 除 Boolean 外的未传递的可选 prop 将会有一个默认值 undefined。
- Boolean 类型的未传递 prop 将被转换为 false。这可以通过为它设置 default 来更改——例如:设置为 default: undefined 将与非布尔类型的 prop 的行为保持一致。
- 如果声明了 default 值,那么在 prop 的值被解析为 undefined 时,无论 prop 是未被传递还是显式指明的 undefined,都会改为 default 值。
- 当 prop 的校验失败后,Vue 会抛出一个控制台警告 (在开发模式下)。
- 如果使用了基于类型的 prop 声明 ,Vue 会尽最大努力在运行时按照 prop 的类型标注进行编译。举例来说,defineProps<{ msg: string }> 会被编译为 { msg: { type: String, required: true }}。