前言
本文主要根据官方文档中的禁用Attribute继承一栏,阅读后加上自己的一些理解和例子的补充。因为在参阅Vue官方文档过程中,有一些内容作者没有加上例子配合解释(可能觉得太简单了吧哈哈),所以有些含糊不清,初学者不是很能理解,所以写了这个系列。在自己的理解上加上一些例子,希望能帮助你更好的理解。
引入问题
当我们注册了一个全局组件时,父组件调用该子组件时传入的attribute值会被子组件的根元素默认继承,可能有些拗口,一起来看下下面的例子。
Vue.component('base-input', {
template: `
<label>
<input/>
</label>
`
})
定义一个元素去调用这个组件,如下:
<div id="demo">
<base-input placeholder="Enter your username" :data="4"></base-input>
</div>
此时HTML结构会是啥样呢?
可以看到,父组件调用子组件时传入的两属性全在根节点label上,而我们本意是把两个属性给到组件内部的input标签。这当然不够不灵活,自然Vue也想到了这一点,接下来带大家了解下Vue是怎么去解决这种情况的。
解决问题
官方文档里给组件提供了一个选项 inheritAttrs: false 。但请注意 inheritAttrs: false 选项不会影响 style 和 class 的绑定。让我们试着加进去去看下效果,组件代码如下:
Vue.component('base-input', {
inheritAttrs: false,
template: `
<label>
<input/>
</label>
`
})
再让我们看下HTML结构:
可以看到他已经不会默认把父组件传的属性继承给根元素了,但是input上也没有出现我们想要的两个属性,这里我们还需要借助Vue里的一个API: $attrs 。这个API是什么呢?让我们看下API文档里的解释:
- 类型:
{ [key: string]: string }
- 只读
- 详细:包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (
class和style除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class和style除外),并且可以通过v-bind="$attrs"传入内部组件——在创建高级别的组件时非常有用。
总的来说 $attrs 就是包括父组件传递的所有属性(不包括被声明成prop的以及class和style),那我们上文提到的data和placeholder属性也应该在$attrs里面了。让我们试试看,还是去修改组件内的代码:
Vue.component('base-input', {
inheritAttrs: false,
template: `
<label>
<input v-bind="$attrs"/>
</label>
`
})
此时HTML结构是否符合我们的要求呢?
自此我们的要求以及对组件里 inheritAttrs 这个选项和 $attrs 这个API有了大致的了解。下面让我们通过一个例子把这两个东西过一遍。
全局组件代码如下:
Vue.component('base-input', {
inheritAttrs:false,
props:['data'],
template: `
<label :data="data">
<input v-bind="$attrs"/>
</label>
`
})
调用该组件代码如下:
<div id="demo">
<base-input placeholder="Enter your username" :style="{fontSize: '20px'}" :data="2"></base-input>
</div>
运行之前,让我们结合上面的知识点去分析下。
- 全局组件将选项
inheritAttrs置为false,说明属性已经不会默认继承到根元素了,除了class和style,所以上面的style属性会出现在label元素上。 - data属性被注册成了prop,且在label上引用了,所以data属性也会出现在label上。
- input元素上绑定了
$attrs,但此时$attrs上还有什么呢?class,style本来就不在。data被注册成prop也被排除在外,只剩placeholder属性。因此placeholder属性会出现在input标签上。
让我们去验证下我们的想法,浏览器里HTML结构如下:
如果你也分析对了,恭喜你也跟我一样了解且初步掌握这两个知识点。 想了解更多用法请移步官方文档。 感谢阅读!
父作用域的绑定 ( class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。
总结来看,attrs里面了。让我们试试看, 还是去修改组件内的代码:
Vue.component('base-input', {
inheritAttrs: false,
template: `
<label>
<input v-bind="$attrs"/>
</label>
`
})
此时HTML结构是否符合我们的要求呢?
自此我们的要求以及对组件里 inheritAttrs 这个选项和 $attrs 这个API有了大致的了解。下面让我们通过一个例子把这两个东西过一遍。
全局组件代码如下:
Vue.component('base-input', {
inheritAttrs:false,
props:['data'],
template: `
<label :data="data">
<input v-bind="$attrs"/>
</label>
`
})
调用该组件代码如下:
<div id="demo">
<base-input placeholder="Enter your username" :style="{fontSize: '20px'}" :data="2"></base-input>
</div>
运行之前,让我们结合上面的知识点去分析下。
- 全局组件将选项
inheritAttrs置为false,说明属性已经不会默认继承到根元素了,除了class和style,所以上面的style属性会出现在label元素上。 - data属性被注册成了prop,且在label上引用了,所以data属性也会出现在label上。
- input元素上绑定了
$attrs,但此时$attrs上还有什么呢?class,style本来就不在。data被注册成prop也被排除在外,只剩placeholder属性。因此placeholder属性会出现在input标签上。
让我们去验证下我们的想法,浏览器里HTML结构如下:
如果你也分析对了,恭喜你也跟我一样了解且初步掌握这两个知识点。 想了解更多用法请移步官方文档。 感谢阅读!