非Prop特性指的是,一个未被组件注册的特性。当组件接收了一个非Prop特性时,该特性会被添加到这个组件的根元素上。
示例
<section id="app">
<!-- age 与 sex 是非prop特性(此处特性就是属性) -->
<my-prop :name='name' age=10 sex='nan'></my-prop>
</section>
<script>
Vue.component('my-prop',{
// 此处并没有接收 age 与 sex 特性,那就是说明age与sex未被注册
props:['name'],
template:`
<!-- 非prop特性会被添加到根元素上-->
<div>
<p>{{name}}</p>
</div>`
})
const vm = new Vue({
el: '#app',
data: {
name:'张三',
},
})
</script>
以上面代码为例
<my-prop :name='name' age=10 sex='nan'></my-prop>
props:['name'],
age 和 sex 就是非prop特性(特性就是属性),因为props中并未有注册它们,它们会保存到 $attrs
上 ,
非prop特性默认会将其添加到该组件的根元素上
替换/合并已有的特性
想象一下 <my-cmp>
的模板是这样的:
template:`<input type="date" class="b">`
添加一个特别的类名:
<my-cmp
class="my-cmp"
></my-cmp>
在这种情况下,我们定义了两个不同的 class 的值:
- my-cmp,这是在组件的模板内设置好的
- b,这是从组件的父级传入的
对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。所以如果传入 type=”text” 就会替换掉 type=”date” 并把它破坏!庆幸的是,class 和 style 特性会稍微智能一些,即两边的值会被合并起来,从而得到最终的值:my-cmp b。
禁用特性继承与$attrs
如果不希望组件的根元素继承特性,那么可以在组件选项中设置 inheritAttrs: false
。如:
Vue.component('my-cmp', {
inheritAttrs: false,
// ...
})
使用 inheritAttrs: false
和 $attrs
相互配合,我们就可以手动决定这些特性会被赋予哪个元素。如
<section id="app">
<my-prop :name='name' age=10 sex='nan'></my-prop>
</section>
<script>
Vue.component('my-prop',{
props:['name'],
mounted(){
console.log(this);
console.log(this.$attrs);
},
inheritAttrs: false, //禁用特性继承
template:`
<div>
<p>{{name}}</p>
<!-- 将非prop特性添加到下面这个元素-->
<p v-bind='$attrs'>{{this.$attrs}}</p>
</div>`
})
const vm = new Vue({
el: '#app',
data: {
name:'张三',
},
})
</script>
效果图
注意:inheritAttrs: false 选项不会影响 style 和 class 的绑定。
$attrs
官方解释
资料中的解释
实现祖先组件传递数据给子孙组件
<section id="app">
<my-prop class="son" :name='name' age=10 sex='nan'>
</my-prop>
</section>
<script>
// vm的孙子组件
Vue.component('my-prop-son',{
props:['age','sex'],
template:`
<div>
<button>{{sex}}</button>
</div>
`
})
// vm的儿子组件
Vue.component('my-prop',{
props:['name'],
mounted(){
console.log(this);
console.log(this.$attrs);
},
inheritAttrs: false, //禁用特性继承
template:`
<div>
<p>{{name}}</p>
<!-- 将非prop特性添加到下面这个元素-->
<p v-bind='$attrs'>{{this.$attrs.age}}</p>
<!-- 向子组件 my-prop-son 传递数据,数据是从该子组件的父组件传递过来的-->
<my-prop-son class='grandson' v-bind='$attrs'></my-prop-son>
</div>`
})
const vm = new Vue({
el: '#app',
data: {
name:'张三',
},
})
</script>
效果图
控制台