Vue进阶之inheritAttrs和$attrs

前言

作者两个月前换了一份新工作,刚来公司的时候接了一个新项目,核心的点就是后端返回提前制订好的数据结构,前端根据相应的结构渲染出表单,当时是有一个动态表单组件,但是缺少以下两个功能:

  • 表单嵌套
  • 渲染自定义组件

于是我就给这个表单组件加上了这两个功能,看了组件前作者的代码,内部是使用render函数去构建的组件,再看了一下相应表单控件的构造,所有的控件props都是通过attrs传入,如下:
Vue进阶之inheritAttrs和$attrs_第1张图片

注意上面用红框圈出来的,在input上绑定了$attrs,在传入的options上传入了一个 inheritAttrs 属性;

接下来我们分别来看一下它们代表什么;

inheritAttrs

默认情况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为普通的 HTML attribute 应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrsfalse,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例 property $attrs 可以让这些 attribute 生效,且可以通过 v-bind 显性的绑定到非根元素上

上面是vue官方文档上对inheritAttrs的解释,大概意思就是如果设置了inheritAttrs的值为false,那么所有绑定的props但是在组件内并没有声明,就不会把这些props回退为普通的HTML attribute,举个例子:

// 子组件

// 父组件

上面子组件中定义了a,但没定义b,外部在子组件上绑定了a和b,a会被识别为props,而b就会被回退为普通的HTML attribute,如下:
image.png

如果我们给子组件加上inheriteAttrs: false,渲染结果如下:
image.png
此时b不再是一个普通的HTML attribute,该属性配合$attrs使用就会体现出它的好处了;

$attrs

包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 ( classstyle 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( classstyle 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用

如上是官网的解释,$attrs保存了绑定在组件上不被识别为props的所有属性,上面的例子,b就会被保存到子组件的$attrs中;

如果子组件中包含另一个组件CompB,而CompB刚好有一个b的prop,之前我的做法就是在子组件中定义一个b的prop,然后把b绑定在CompB上,最外层再绑定b;

通过绑定$attrs我们可以不在中间组件声明内部使用组件的props,如下:

// 子组件Comp

因为外层组件传入的b保存在Comp组件的$attrs中,这里通过把Comp实例的$attrs属性绑定在CompB上实现b的绑定,因为inheritAttrs被设置成为了false,所以Comp渲染出的标签上就不会有b;

这也是为什么公司那个表单组件能够正常使用的原因,因为渲染函数传attrs就是在赋值组件实例的$attrs,而elmentUI把实例上的$attrs绑定在了input控件上,所以能实现它应有的功能响应;

总结

  • inhertAttrs:不回退绑定在组件上的非组件内部定义的props回退为普通HTML attributes
  • $attrs:所有不被认为是props的属性都会保存在其中,style和class除外

你可能感兴趣的:(vue.js,前端)