说到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>