组件之间传递数据的方式可能有
- 父组件通过
props
的方式向子组件传值 - 子组件通过
$emit
传递的方法参数向父组件传值 - 使用
vuex
进行状态管理 - 兄弟组件之间可以使用
event bus
事件总线传值 - 非父子组件之间使用
inheritAttrs
+$attrs
+$listeners
传值(跨多级的组件嵌套关系)
这里主要讲最后一种方式传值
应用场景图大概是这样
三个组件,A组件与B组件是父子组件,A组件与C组件是跨多级的组件嵌套关系
代码示例:
fatherA.vue
<template>
<div>
<!-- 此处,v-on 监听了两个事件,可以在子组件和子子组件中直接触发 -->
<child-b :childB="childB" :grandson="grandson" @test1="onTest1" @test2="onTest2"></child-b>
</div>
</template>
<script>
import childB from './childB'
export default {
name: 'fatherA',
components: {
childB
},
data() {
return {
childB: 'myChildB',
grandson: 'myGrandSon'
}
},
methods: {
onTest1() {
console.log('test1 running...')
},
onTest2() {
console.log('test2 running...')
}
}
}
</script>
childB.vue
<template>
<div class="child-b">
<p>in childB</p>
<p>props: {{childB}}</p>
<p>$attrs: {{$attrs}}</p>
<!-- grandsonC 组件中能直接触发 test2 方法的原因在于, childB 组件在调用 grandsonC 组件时,使用
v-on 绑定了 $listeners 属性 -->
<!-- 通过 v-bind 绑定 $attrs 属性,grandsonC 组件可以直接获取到 fatherA 组件中传递
下来的 props (除了 childB 组件中 props 声明的)-->
<grandson-c v-bind="$attrs" v-on="$listeners"></grandson-c>
</div>
</template>
<script>
import grandsonC from './grandsonC'
export default {
props: ['childB'],
inheritAttrs: false,
components: {
grandsonC
},
mounted() {
this.$emit('test1')
}
}
</script>
grandsonC.vue
<template>
<div class="grand-son">
<p>in grandSonC</p>
<p>props: {{grandson}}</p>
<p>$sttrs: {{$attrs}}</p>
</div>
</template>
<script>
export default {
props: ['grandson'],
inheritAttrs: false,
mounted() {
this.$emit('test2')
}
}
</script>
最后的结果
根据结果分析:
B组件中的 $attrs
是父组件A中不被认为是 props
的值,并且B组件通过 v-bind="$attrs"
传入了内部组件C组件中
B组件中通过 v-on="$listeners"
将父组件中的方法传入了内部组件C组件中
$attrs
- 类型:
{ [key: string]: string }
- 只读
- 详细:包含了父作用域中不作为 prop 被识别(且获取)的 attribute 绑定(
class
和style
除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定(class
和style
除外),并且可以通过v-bind="$attrs“”
传入内部组件–在创建高级别的组件时非常有用
$listeners
- 类型:
{ [key: string]: Function | Array<Function> }
- 只读
- 详细:包含了父作用域中的(不含
.native
修饰器的)v-on
事件监听器。它可以通过v-on="$listeners"
传入内部组件-- 在创建更高层次的组件时非常有用
inheritAttrs
- 类型 :
Boolean
- 默认值:
true
- 注意:这个选项不影响
class
和style
的绑定 - 详细:默认情况下,父作用域的不被认作 props 的 attribute 绑定(attribute bindings) 将会 “回退” 且作为普通的 HTML attribute 应用在子组件的根原生上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置
inheritAttrs
为false
,这些默认行为将会被去掉。而通过实例 property$attrs
可以让这些 attribute 生效,且可以通过v-bind
显性的绑定到非根元素上。
这里用上面的代码简单做一个比较示例看一下inheritAttrs
分别设置为true
和false
的区别。我们就使用上面的组件A,B,C的代码做一下示例
先是inheritAttrs: false
组件B和组件C都设置为false
,我们来看源代码的效果
接下来我们把 B组件设置为inheritAttrs: true
看一下源代码效果
这个时候就验证了inheritAttrs
的详细说明中的内容