关于非props属性
这是官网原文内容:
一个非 prop 的 attribute 是指传向一个组件,但是该组件并没有相应 prop 定义的 attribute。
因为显式定义的 prop 适用于向一个子组件传入信息,然而组件库的作者并不总能预见组件会被用于怎样的场景。这也是为什么组件可以接受任意的 attribute,而这些 attribute 会被添加到这个组件的根元素上。
原谅我发量尚可,脑瓜不够亮,于是自己写例子尝试:
首先,正常的prop传递应该是这样的:父传子承
<div id='app'>
<simple-demo title="我是标题"></simple-demo>
</div>
Vue.component('SimpleDemo', {
props: ['title'],
template: '<div>{{title}}</div>'
})
var app = new Vue({
el: '#app'
})
后台F12查看元素啥样:
<div>我是标题</div>
结果:props属性顺利传递到子组件,并且在子组件的模板内可以直接通过插值表达式用,title这个属性也没有显示在子组件最外层HTML元素上
其次,这样顺顺利利的样子太不够味道了,来一个父传子不承的叛逆例子
删掉子组件的props选项
Vue.component('SimpleDemo', {
template: '<div>{{title}}</div>'
})
后台报错了,title这个属性或方法没有被定义。为了避开这个错误,我们把双大括号内的内容删掉,改成文字。
Vue.component('SimpleDemo', {
template: '<div>漂亮</div>'
})
后台F12查看元素啥样:
<div title="我是标题">漂亮</div>
结果:props属性在子组件的模板内不可以直接通过插值表达式用,并且title这个属性显示在子组件最外层HTML元素上
关于禁用Attribute继承
官网上的例子比较让我困惑,这里就不再全部引用,下面是我适当改装后的例子
首先,通过上面的例子,我们知道父组件向子组件传值,如果子组件没有接收,它会显示在子组件最外层的HTML元素上。
<div id="app">
<base-input
v-model="username"
required
placeholder="Enter your username"
></base-input>
</div>
Vue.component('base-input', {
template: `
<label>
用户名<input/>
</label>
`
})
var app = new Vue({
el: '#app',
data: {
username: 'hello',
}
})
通过F12审查元素,果不其然,页面显示为这样:
<label required="required" placeholder="Enter your username" value="hello">
用户名<input>
</label>
注意:value属性是<base-input>元素定义的v-model赋予的
然而,需要这些属性的不是<label>元素,是里面的<input>,那我们给子组件添加一个禁用Attribute的选项设置,不让这些属性显示在<label>上
Vue.component('base-input', {
inheritAttrs: false,
template: `
<label>
用户名<input/>
</label>
`
})
通过F12审查元素,已经成功了:
<label>
用户名<input/>
</label>
但是,我们需要实现父子组件之间的数据交换。如何才能在添加禁用Attribute的选项情况下,让<base-input>接收父组件传递的属性值呢?
官方提供了一个$attrs property,可以这样使用:
Vue.component('base-input', {
inheritAttrs: false,
template: `
<label>
用户名
<input
v-bind:value="$attrs.value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})
结果:完美实现了我们想要的效果
但是关于$attrs我还有些发现:
<div id="app">
<base-input
v-model="username"
required
placeholder="Enter your username"
></base-input>
</div>
Vue.component('base-input', {
inheritAttrs: false,
template: `
<label>
{{$attrs}}
</label>
`
})
结果是一个对象:
{ "required": "", "placeholder": "Enter your username", "value": "hello" }
当我在子组件里面添加props,接收placeholder属性后
Vue.component('base-input', {
inheritAttrs: false,
props: ['placeholder'],
template: `
<label>
{{$attrs}}
</label>
`
})
结果显示:
{ "required": "", "value": "hello" }
注意:对比上一个例子,发现$attrs中的placeholder这个键值对都没了!!
于是,子组件内的$attrs里面的都是非props属性(父组件已传递,但是子组件未接收的属性)
ps:一点拙见,某些地方的描述词汇不是很准确,望指出。