vue $attrs、$listeners、inheritAttrs的理解
$attrs
包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 props 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件——在创建更高层次的组件时非常有用。
$listeners
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件——在创建更高层次的组件时非常有用。
inheritAttrs
默认情况下父作用域的不被认作 props 的特性绑定 (attribute bindings) 将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例属性 $attrs 可以让这些特性生效,且可以通过 v-bind 显性的绑定到非根元素上。
下面举个例子说明,有这样三个组件,组件A、B、C,他们的关系是这样的
组件A如果向组件B传值的话,可以不用在组件B的props定义,可以通过$attrs直接获取
组件A
<template>
<div class="a">
<test1 :a="1" />
</div>
</template>
组件B
<template>
<div class="b">
B
{{ $attrs }}
</div>
</template>
这样就可以获取到了
这时候我们看一下dom,发现组件B的根元素上带有a=1
如果我们不想要这一特性的话,只需要在组件B这样设置
export default {
inheritAttrs: false,
}
如果我们想要组件A向组件B传的值,组件C也可以获取到,那么我们就要使用到v-bind="$attrs"
组件B
<div class="b">
B
{{ $attrs }}
<test2 v-bind="$attrs" b="2" />
</div>
组件C
<template>
<div class="test2">
C
{{ $attrs }}
</div>
</template>
可以看到,组件C已经获取到组件A的值
如果我们想组件C向组件A提交事件,可以先向组件B$emit
,然后组件B向组件A$emit
,但是这样很麻烦,我们可以使用v-on="$listeners"
组件C
<template>
<div class="c">
C
<button @click="test2">text2</button>
{{ $attrs }}
</div>
</template>
methods: {
test2() {
this.$emit('test2', 'test2')
}
}
组件B
<template>
<div class="b">
B
{{ $attrs }}
<test2 v-bind="$attrs" b="2" v-on="$listeners" />
</div>
</template>
组件A
<template>
<div class="dashboard-container">
<test1 :a="1" @test2="test2" />
</div>
</template>
methods: {
test2(value) {
console.log(value)
}
}
可以看到,这个时候组件A已经获取到了组件C传递的事件