vue多層嵌套組件傳值

說到vue組件傳值,大概分爲如下幾種狀況vue

1.父傳子

父組件經過屬性綁定將值傳給子組件,子組件經過props進行接收vuex

2.子傳父

父組件經過v-on監聽方法,子組件經過$emit觸發父組件的方法,將數據做爲回調函數的參數傳給父組件segmentfault

3.兄弟組件傳值

經過定義一個eventBus經過on和emit機制來實現事件的綁定和觸發,實現數據的流動。如今常見的是用vuex來實現數據的共享和流動。api

多層嵌套組件傳值

問題描述:

除此外,今天遇到一個狀況,組件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官網上了解幾個概念this

  • 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中接收他,確定是沒有用,那確定不指望有這樣的事情發生,「經過設置 inheritAttrsfalse,這些默認行爲將會被去掉。」原來設置爲false就能夠阻止這樣的行爲。
      回到咱們的需求,組件B和組件C做爲一箇中間組件,並不須要接收,就能夠設置inheritAttrs爲false便可實現code

  • vm.$attrs
    包含了父做用域中不做爲 prop 被識別 (且獲取) 的 attribute 綁定 (classstyle 除外)。當一個組件沒有聲明任何 prop 時,這裏會包含全部父做用域的綁定 (classstyle 除外),而且能夠經過 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組件component

<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>
相關文章
相關標籤/搜索