说到 vue 组件传值,大略分为以下几种状况
1. 父传子
父组件通过属性绑定将值传给子组件,子组件通过 props 进行接管
2. 子传父
父组件通过 v -on 监听办法,子组件通过 $emit 触发父组件的办法,将数据作为回调函数的参数传给父组件
3. 兄弟组件传值
通过定义一个 eventBus 通过 on 和 emit 机制来实现事件的绑定和触发,实现数据的流动。当初常见的是用 vuex 来实现数据的共享和流动。
多层嵌套组件传值
问题形容:
除此外,明天遇到一个状况,组件 A,B,C,D, 四个组件之间的关系为嵌套关系,即组件 A > 组件 B > 组件 C > 组件 D, 然而组件 D 中想要触发组件 A 中的办法。
因为一开始的时候没有把设计到的数据放到 vuex 中且是做的公共组件的封装,放在 vuex 外面也不适合。在 vue 的官网上也看了,看到了 inheritAttrs 属性,第一开始没有看明确文档形容的意思,起初在 segmentfault 中看到一篇讲 vue 多层嵌套传值的文章。借助外面的 demo 和 vue 官网,终于如同有点明确多层嵌套传值的意思。
解决思路
一开始也有思考过子组件一层一层的往上 emit, 直到 A 组件监听到这个事件。然而思考到 B 组件和 C 组件作为两头组件并没有用到这个办法,只单纯定义个办法去吧数据 emit 到上一层组件中。每一层组件都须要去实现工夫监听,按情理这个办法也能够实现,然而总感觉办法有点笨,想着把这种办法作为 planB, 先尝试一下,如果找不到适合的解决方案的话,再驳回这个计划。
我想实现的计划简略来说就是 D 能够触发 A 中的办法,然而两头组件不须要帮忙传递。
解决过程
在解决问题之前,首先须要在 vue 官网上理解几个概念
-
inheritAttrs
默认状况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为一般的 HTML attribute 利用在子组件的根元素上。当撰写包裹一个指标元素或另一个组件的组件时,这可能不会总是合乎预期行为。通过设置 `inheritAttrs` 到 `false`,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例 property `$attrs` 能够让这些 attribute 失效,且能够通过 `v-bind` 显性的绑定到非根元素上。
在一开始的时候我读了两遍都没有读懂 inheritAttrs 的形容(理解能力真的略微有点差)。我集体的了解是这样的。
如果 A 组件外面援用了 B 组件,A 组件是父组件,B 组件是子组件,A 组件给 B 组件传值通过属性绑定,B 组件通过 prop 接管,当然 B 组件必定只会承受本人须要的属性。如果 B 组件不须要 name 属性,然而 A 组件偏偏要传给 B 组件,然而 B 组件并没有在 props 中接管,那么这个值必定是传过来了呀,然而那里去了呢,而后再来读这段话,“父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为一般的 HTML attribute 利用在子组件的根元素上。”,意思就是 name 属性没有在 props 里承受,就会主动绑定到 B 组件的根组件下来。然而既然 B 组件既然不在 props 中接管他,必定是没有用,那必定不冀望有这样的事件产生,“通过设置inheritAttrs
到false
,这些默认行为将会被去掉。”原来设置为 false 就能够阻止这样的行为。
回到咱们的需要,组件 B 和组件 C 作为一个两头组件,并不需要接管,就能够设置 inheritAttrs 为 false 即可实现 - vm.$attrs
蕴含了父作用域中不作为 prop 被辨认 (且获取) 的 attribute 绑定 (class
和style
除外)。当一个组件没有申明任何 prop 时,这里会蕴含所有父作用域的绑定 (class
和style
除外),并且能够通过v-bind="$attrs"
传入外部组件——在创立高级别的组件时十分有用。
父组件传值给子组件,子组件通过 prop 承受了一部分,然而咱们如何能够获取到没有接管的那局部呢,哈哈,就是通过 $attrs。外面蕴含所有父作用域的绑定,划重点!!!, 能够通过v-bind="$attrs"
传入外部组件
这样离咱们的需要是不是越来越近了,属性就能够往外部组件传递那事件监听还远吗!!! - $listeners
蕴含了父作用域中的 (不含.native
润饰器的)v-on
事件监听器。它能够通过v-on="$listeners"
传入外部组件——在创立更高层次的组件时十分有用。
是的,没错他来了, 通过v-on="$listeners"
传入外部组件!!!
理解完这三个概念,我的问题就迎刃而解。
总结
1. 如果在 D 中想触发 A 中的 handlePreview 办法,首先 A 组件对该办法进行监听
2. 在 B 组件和 C 组件中设置 inheritAttrs 为 false, 不做接管,而后把数据和事件往外部组件接着传(我本次需要只有办法,没有属性,为了加深学习印象就把 v-bind="$alert"
一起传递了)
3. 到了 D 组件中,通过 $emit 触发 A 组件中的办法,顺利完成我的需要。
以下内容为代码片段(vue 语法),大略表述出大略意思。
参考文章链接:vue 多级嵌套组件传参
A 组件
<template>
<div> A 组件
<BComponent @handlePreview="preview"</BComponent>
</div>
</template>
B 组件
<template>
<div> B 组件
<CComponent v-bind="$alert" v-on="$listeners" ></CComponent>
</div>
</template>
<script>
export default {
name: 'b-component',
inheritAttrs: false
}
</script>
C 组件
<template>
<div> C 组件
<DComponent v-bind="$alert" v-on="$listeners" ></CComponent>
</div>
</template>
<script>
export default {
name: 'c-component',
inheritAttrs: false
}
</script>
D 组件
<template>
<div> D 组件
<button @click="handleClick"></button>
</div>
</template>
<script>
export default {
name: 'c-component',
methods:{handleClick(){this.$emit('handlePreview')
}
}
}
</script>