Vue官方文档解读系列(一):禁用 Attribute 继承

1,376 阅读2分钟

前言

本文主要根据官方文档中的禁用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结构会是啥样呢? 2OUDDP2M}E4)Q}7VZW%}6KG.png

可以看到,父组件调用子组件时传入的两属性全在根节点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 绑定 (classstyle 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (classstyle 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。

总的来说 $attrs 就是包括父组件传递的所有属性(不包括被声明成prop的以及class和style),那我们上文提到的data和placeholder属性也应该在$attrs里面了。让我们试试看,还是去修改组件内的代码:

Vue.component('base-input', {
  inheritAttrs: false,
  template: `
    <label>
    <input v-bind="$attrs"/>
    </label>
   `
})

此时HTML结构是否符合我们的要求呢?

~E9@%309[46K)B@VW_]7JHY.png

自此我们的要求以及对组件里 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结构如下:

CEGSZ2@E0E5KZ)C}5JM%09R.png

如果你也分析对了,恭喜你也跟我一样了解且初步掌握这两个知识点。 想了解更多用法请移步官方文档。 感谢阅读!

父作用域的绑定 ( classstyle 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。

总结来看,attrs就是包括父组件传递的所有属性(不包括被声明成prop的以及classstyle),那我们上文提到的dataplaceholder属性也应该在attrs就是包括父组件传递的所有属性(不包括被声明成prop的以及class和style),那我们上文提到的data和placeholder属性也应该在attrs里面了。让我们试试看, 还是去修改组件内的代码:

Vue.component('base-input', {
  inheritAttrs: false,
  template: `
    <label>
    <input v-bind="$attrs"/>
    </label>
   `
})

此时HTML结构是否符合我们的要求呢? ~E9@%309[46K)B@VW_]7JHY.png

自此我们的要求以及对组件里 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结构如下: CEGSZ2@E0E5KZ)C}5JM%09R.png

如果你也分析对了,恭喜你也跟我一样了解且初步掌握这两个知识点。 想了解更多用法请移步官方文档。 感谢阅读!