prop
通过 Props 传递数据
每个组件实例都有它自己的作用域.这意味着你不能也不应该在子组件的模板内直接引用父组件的数据。数据应该通过props传递下去给子组件.
一个prop是一个承载了父组件传递信息的自定义属性.子组件需要显示的用props选项声明它所期望接收到的数据(如名称、类型、默认值等):
Vue.component('child', {
// declare the props
props: {
message: [String, Number],
propA: {
type: Number,
default: 100
}
},
// just like data, the prop can be used inside templates
// and is also made available in the vm as this.message
template: '<span>{{ message }}</span>'
})
然后我们可以像下面这样传递一个普通字符给子组件
<child message="hello!"></child>
Result:
Hello!
camelCase(驼峰式) vs. kebab-case(短横线隔开式)
HTML属性是不区分大小写的,所以当我们没使用字符串模板时,驼峰式写法需要转换成与之相对应的短横线隔开式命名;
Vue.component('child', {
// camelCase in JavaScript
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>'
})
<!-- kebab-case in HTML -->
<child my-message="hello!"></child>
🙃如果你使用的是字符串模板则没有这个限制.
动态Props
与给一个普通属性绑定表达式类似,我们也可以在父组件中用v-bind
指令来动态绑定一个数据到props
.当这个数据在父组件中有更新后,子组件中也会相应得到更新:
<div>
<input v-model="parentMsg">
<br>
<child v-bind:my-message="parentMsg"></child>
</div>
一般都会采用简写的形式
<div>
<child :my-message="parentMsg"></child>
</div>
字面量语法 vs 动态语法
新手常犯的一个错误就是试图通过字面量语法传递一个数值,就像下面所示:
<!-- this passes down a plain string "1" -->
<comp some-prop="1"></comp>
然而,由于这是一个字面量属性,它的值会以普通字符串'1'传递导子组件,而不是数值1.如果我们相要传递一个真正的数值,需要使用v-bind
指令,从而它的值会被当成一个js表达式来对待.
<!-- this passes down an actual number -->
<comp v-bind:some-prop="1"></comp>
单向数据流
prop是单向绑定的:当父组件的属性更新时,会传导给子组件,但不会反过来.这样是为了防止子组件无意中更改了父组件的状态而让你的应用数据流变得难以理解.
另外,每次父组件更新时,子组件的所有props都会更新为最新的值.这意味着你不应该在子组件中试图修改某个prop.如果你这么做了,Vue会在Console中给出警告.
通常会有这两种情形试图修改prop:
- prop 作为初始值传入后,子组件想把它当作局部数据来用;
- prop 传入后需要进行转换才能得到相应的值;
应对这些情形的正确方式:
1.定义一个局部变量并用prop传进来的初始值来初始化它;
props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}
2.定义一个计算属性通过对prop的计算来获取所需要的值(这样也不会更改影响到父级的数据):
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态(可以拷贝一个对象)。
Prop验证
我们可以为一个组件的prop传值指定相应的验证规则.如果任一要求没有满足,Vue会发出警告.当你是某个组件的作者且想让其它人所使用时,这个特性十分有用.
不像定义一个props那样用字符串数组,你需要用对象的形式来指定验证的规则:
Vue.component('example', {
props: {
// 基础类型检测 (`null` 意思是任何类型都可以)
propA: Number,
// 多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数字,有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}
})
type
可以是下面列出的原生构造器:
- String
- Number
- Boolean
- Function
- Object
- Array
type
也可以是一个自定义构造器函数,使用 instanceof 检测。
当 prop 验证失败,Vue会在Console抛出警告 (如果使用的是开发版本)。
这是一条评论~