1x1 精读Vue官方文档 - Prop
发布于 2022年 02月 23日 04:22
精读 Vue 官方文档系列 🎉
Prop 的大小写
Prop 的命名支持以下两种方式:
- camelCase : 驼峰命名法中的小驼峰。
- kebab-case : 分隔符命名法
虽然 Vue 模板的编译器可以同时支持以上两种命名方式,但受限于浏览器对大小写字母的不敏感,再加上 W3C 推荐的是 kebab-case
方式来作为自定义元素的命名规范,所以,在最佳实践中,我们会以 kebaba-case
方式来命名元素与 Attribute,而在组件的逻辑中,则使用 camelCase
方式。
<blog-post :post-id="post.id" :post-content="post-content" name="article" />
export default {
name:'MyComponent',
props:['postId','postContent']
}
Prop 类型
使用 props 属性来声明组件使用到的 prop
只有通过 props
选项声明后的 prop 才能被组件实例访问,值通常是一个字符串数组。
prop 类型
如果希望为每个 prop 指定值的类型,那么可以通过对象的形式列出 prop。 为 prop 值指定类型的好处:
- 规范组件文档。
- 类型检测与提示。
默认类型
将浏览器内置的原生构造函数作为类型。
例如:Number
、String
、Date
、Boolean
、Object
、Array
、Promise
、Function
、Symbol
。
自定义类型
prop 值的类型也可以是一个自定义构造函数,Vue 会自动通过 instanceof
运算符去比较。
props:{
jack:Human
}
传递静态或动态 Prop
传递静态数据
传递静态数据,普通字符串,直接使用 HTML Attribute 的方式赋值。
<my-component name="article" />
传递动态数据
传递动态数据、变量或响应式对象、需要使用 v-bind
指令动态赋值。
<my-component :post-id="post.id" />
静态赋值与动态赋值对比
传输字符串类型
<my-component name="article" />
<my-component2 :name="'article'" />
传入对象类型
<!--组件接收的实际上是一个字符串,需要自己 JSON.parse-->
<my-component post="{name:'article',content:'content'}" />
<my-component2 :post="data.post" />
传入一个对象的所有 property
将一个对象的所有”键值对“作为 prop 传递到子组件。
实现非常简单,为v-bind
指令赋值。
export default {
data(){
return {
post:{title:'post title'},
property:{name:'name', title:'title', description:'desc'}
}
}
}
<my-component v-bind="property" :post-title="post.title"/>
export default {
name:'MyComponent',
props:['title', 'name', 'description', 'postTitle']
}
单向数据流
为了让数据流向更加清晰,Vue 规定父子之间的 Prop 传递只能是一个单向下行绑定,即父级 prop 的更新会向下流到子组件中,并触发子组件更新,但反过来则不行,以防止子组件意外变更父级的状态。
如果强行在子组件中变更父级传递的 prop,则 Vue 会在控制台抛出警告⚠️
需要变更 prop 的常见情形有:
接收父组件通过 prop 传递的一个初始值,并且需要对这个值进行变更。
建议将父级的 prop 转换为组件自身的 `data`。
父组件传入的 prop 需要进行转换方能使用
推荐使用 `computed` 属性。
对于引用类型的值,例如数组或对象,很容易会在子组件中被误改,从而影响父组件的状态。
Prop 验证与类型检查
为 props 中的值提供一个具有验证功能的对象,而不是单单一个字符串数组。
简单的类型验证与自定义类型验证:
{
props:{
name:String,
post:[Object, Array],
author:Person,
symb:Symbol
}
}
默认值或必填值:
{
props:{
name:{
type:String,
default:'jack'
},
age:{
type:Number,
default:function(){
if(sex==='male'){
return 10;
}
return 9;
}
},
sex:{
type:Number,
required:true
}
}
}
自定义验证函数:
{
props:{
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
}
当 prop 验证失败的时候,(开发版本) Vue 将会产生一个控制台的警告。 注意这些 prop 会在组件的实例创建之前便会进行验证,所以对于
default
、validator
等函数中是访问不到组件的实例的。
非 Prop 的 Attribute
Prop 一定是 Attribute,但并不是所有的 Attrbiute 都是 Prop。只有在组件的 props
选项中声明的 Attribute 才会是 Prop。
组件默认接收所有 Attribute 并添加到组件的根元素上,好处在于未来组件的扩展。
Attribute 的继承
通过组件的 inheritAttrs:true|false
选项便可以开启/关闭组件的 Attribute 继承。
默认为启用继承,此时为组件添加的非 Prop 的 Attribute 会自动附加在组件的根元素上。
export default {
name: "MyInput",
inheritAttrs:true,
template:'<input />'
};
<my-input type="text" size="15" placeholder="please enter your username" />
最终渲染的HTML结果为:
<input type="text" size="15" placeholder="please enter your username">
如果设置 inheritAttrs
为 false
,则渲染的结果为
<input>
Attribute 的替换与合并
Attribute 的继承又带来了新的问题,如果组件的根元素已经存在了与父级传入相同的 Attribute,那么 Vue 会用传入的值替换组件内设置好的值。但是对于 class
与 style
两个 Attribute 会稍微智能一些,Vue 会合并传入的值,而不是进行替换操作。
Attribue 的分发
为了增强撰写基础组件的能力,我们有时会需要禁用 Attribute 的继承,并不总是希望组件的根元素去继承 Attribute,而是可以由开发者手动分配。庆幸的是通过组件实例的 $attrs
属性结合组件 inheritAttrs
选项,我们可以手动决定 Attribute 应该要被赋予哪些元素上。
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})
这个模式允许你在使用基础组件的时候更像是使用原始的 HTML 元素,而不会担心哪个元素是真正的根元素。
注意 inheritAttrs: false 选项不会影响 style 和 class 的绑定。