props概念
props是自定义属性,合理使用props可以极大的提高组件的复用性
- 作用: 接收来自父组件的数据
- 本质: 数组(Array)|对象(Object)
- 扩展: 对象形式允许配置高级选项,如类型检测、自定义验证、设置默认值
简单接收
<!-- App.vue -->
<Child codeFontEnd="codeFontEnd" codeBackEnd="codeBackEnd" />
// Child.vue
export default {
props:['codeFontEnd','codeBackEnd']
}
- 在子组件的模板中就可以直接使用
<!-- Child.vue -->
<h1> 前端:{{codeFontEnd}}</h1>
<h1> 后端:{{codeBackEnd}}</h1>
配置选项
- 写成对象形式的
props,可以为每个prop指定值的类型 - 传递错误的类型时,浏览器控制台会警告用户
props: {
title: String, // 指定类型为字符串
likes: Number, // 指定类型为数字
isPublished: Boolean, // 指定类型为布尔值
commentIds: Array, // 指定类型为数组
author: Object, // 指定类型为对象
callback: Function, // 指定类型为函数
contactsPromise: Promise // 指定类型为Promise
}
-
单个
prop也可以写成对象形式,主要有以下配置项- type: 定义prop的类型可以是原生构造函数:如
String、Number、Boolean、Array等、或是自定义构造函数、或上述内容组成的数组 - default: 为该
prop指定一个默认值,如果该prop没有被传入,则使用默认值 - required: 定义该
prop是否是必填项 - validator: 自定义验证函数,会将该
prop的值作为唯一的参数代入
- type: 定义prop的类型可以是原生构造函数:如
注意:对象或数组的默认值必须从一个工厂函数返回
// 数组
props:{
type:Array
default:() => [] // 数组的默认值
}
// 对象
props:{
type:Object
default:() => ({}) // 对象的默认值
}
- 示例: 在
Child组件中配置props选项,性别和姓名必须传进,年龄默认值为19,且必须为数字
props:{
name:{
type:String, // name的类型是字符串
required:true // name是必要的
},
sex:{
type:String,
required:true
},
age:{
type:Number,
default:19, // 默认值是19
validator(age){
return typeof age === 'number' && !Number.isNaN(age)
}
}
}
注意:
prop会在组件实例创建之前进行验证,所以组件的options (如data、computed等) 在default或validator函数中是无法访问的
- 在App组件中不传姓名和年龄,控制台会报出警告,而年龄用默认值代替
如何接收多类型?
type选项可以为数组,数组中指定可以接收的类型
props: {
author: { type: ['Array','Object']}
}
动态传递
- 可以通过
v-bind动态赋值 - 用
v-bind修饰的不再是字符串,而是JavaScript表达式
①传入一个数字
<Child :age="18"/>
②传入一个布尔值
<Child :isShow="true" />
<!-- prop没有值的情况都为true -->
<Child isShow />
③传入一个数组
<Child :userIdList="[234, 266, 273]" />
④传入一个对象
<Child :userIdList="{ fontEnd:'JavaScript' }" />
⑤传入一个对象的所有属性
<Child v-bind="user" />
data(){
return {
user: {
name: '张三',
age: 18
}
}
}
- 等价于下面写法
<Child :name="user.name" :age="post.age" />
单向数据流
- 用
props传递的数据只能在父级更新,向下流动到子组件中,反之则会发出警告 - 防止从子组件意外变更父级组件的状态,从而导致数据流向难以理解
- 在子组件Child中接收父组件的数据,并尝试修改
<h1> 姓名:{{ name }}</h1>
<button @click="name='ls'">修改姓名</button>
export default {
name:'Child',
props:['name']
}
- 浏览器控制台发出警告
如何更改父组件传递的数据呢?
①把 props 的值转存到 data 中,因为 data 中的数据可读可写
props: ['name'],
data() {
return {
userName: this.name
}
}
②使用计算属性进行转换
props: ['size'],
computed: {
newSize() {
return this.size.trim().toLowerCase()
}
}
③传入引用类型数据,对其中的属性作出更改
props: {
user:{
type: Object,
default: ()=>({})
}
}
注意: 对象和数组是通过引用传入的,在子组件中改变这个对象或数组本身将会影响到父组件的状态
④在传递时使用 .sync 修饰符,打破数据单向流
<Child :name.sync="name" />
- 在子组件通过
update事件进行更改
this.$emit('update:name','ls')