摘要:是一個事件,它向下傳播到當前實例的所有后代。由于后代擴展為多個子樹,事件傳播將會遵循許多不同的路徑。組件修改實現遞歸地在父鏈上傳播事件。
組件通信
父傳子 props屬性 子傳父 $emit事件
這兩種官方文檔里有很詳細的介紹就不解釋了
還是舉個栗子:
//parent.vue父組件parent: {{money}}//兩種寫法都可以,是語法躺;.sync表示同步,如果只傳value 用v-model即可
//子組件SON //單項數據流,父給子綁定一個事件son:{{value}}
*
$dispatch 和 $broadcast (Vue1中可以用來實現基于組件樹結構的事件流通信,vue2中已經被移除)
(父要傳到孫;孫要傳到父;)
dispatch 是一個事件,首先會在自己實例本身上觸發,然后沿父鏈向上傳播。 broadcast 是一個事件,它向下傳播到當前實例的所有后代。由于后代擴展為多個子樹,事件傳播將會遵循許多不同的“路徑”。 除非回調返回 true,否則在沿該路徑觸發偵聽器回調時,每個路徑的傳播將會停止。
//grandoon.vue組件grandson:{{value}}
//dispatch實現 /** * Recursively propagate an event up the parent chain. * 遞歸地在父鏈上傳播事件。 * @param {String} event * @param {...*} additional arguments */ // $dispatch 方法是定義在 Vue 的 prototype 上的 // 接受一個字符串類型的事件名稱 Vue.prototype.$dispatch = function (event) { // 首先執行 $emit 觸發事件,將返回值保存在 shouldPropagate 中 var shouldPropagate = this.$emit.apply(this, arguments) // 如果首次執行的 $emit 方法返回的值不是 true 就直接返回 // 如果返回值不是 true 就說明組件邏輯不希望事件繼續往父組件進行傳遞 if (!shouldPropagate) return // 如果首次執行 $emit 方法返回值是 true 就獲取當前組件的 parent 組件實例 var parent = this.$parent // 將函數接受的參數轉換成數組 var args = toArray(arguments) // use object event to indicate non-source emit on parents // 根據傳入的事件名稱的參數組裝成 object args[0] = { name: event, source: this } // 循環知道組件的父組件 while (parent) { // 在父組件中執行 $emit 觸發事件 shouldPropagate = parent.$emit.apply(parent, args) // 如果父組件 $emit 返回的是 true 就繼續遞歸祖父組件,否則就停止循環 parent = shouldPropagate ? parent.$parent : null } // 最后返回當前組件實例 return this }
broadcast 實現 Vue.prototype.$broadcast = function (event) { // 獲取傳入事件的類型,判斷是否為字符串 var isSource = typeof event === "string" // 校正 event 的值,當接受 event 的類型為字符串時就直接使用,如果不是字符串就使用 event 上的 name 屬性 event = isSource ? event : event.name // if no child has registered for this event, // then there"s no need to broadcast. // 如果當前組件的子組件沒有注冊該事件,就直接返回,并不用 broadcast if (!this._eventsCount[event]) return // 獲取當前組件的子組件 var children = this.$children // 將函數接受的參數轉換成數組 var args = toArray(arguments) // 如果傳入事件為字符串 if (isSource) { // use object event to indicate non-source emit // on children // 根據傳入的事件名稱的參數組裝成 object args[0] = { name: event, source: this } }
*
現在我們來討論一種情況,A組件與C組件怎么通信,我們有多少種解決方案?
我們使用VueX來進行數據管理,但是如果項目中多個組件共享狀態比較少,項目比較小,并且全局狀態比較少,那使用VueX來實現該功能,并沒有發揮出VueX的威力。
使用B來做中轉站,當A組件需要把信息傳給C組件時,B接受A組件的信息,然后利用屬性傳給C組件,這是一種解決方案,但是如果嵌套的組件過多,會導致代碼繁瑣,代碼維護比較困難;如果C中狀態的改變需要傳遞給A, 使用事件系統一級級往上傳遞 。
自定義一個Vue 中央數據總線,這個情況適合碰到組件跨級傳遞消息,但是使用VueX感覺又有點浪費的項目中,但是缺點是,碰到多人合作時,代碼的維護性較低,代碼可讀性低
在vue2.4中,為了解決該需求,引入了$attrs?和$listeners ,?新增了inheritAttrs?選項。
$attrs (屬性集合) $listeners (方法集合) v-bind="$attrs", v-on="$listeners" $attrs包含了父作用域中不作為 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外)
1.provide就相當于加強版父組件prop
2.inject就相當于加強版子組件的props?
因為以上兩者可以在父組件與子組件、孫子組件、曾孫子...組件數據交互,也就是說不僅限于prop的父子組件數據交互,只要在上一層級的聲明的provide,那么下一層級無論多深都能夠通過inject來訪問到provide的數據
//父組件
缺點:
這么做也是有明顯的缺點的,在任意層級都能訪問導致數據追蹤比較困難,不知道是哪一個層級聲明了這個或者不知道哪一層級或若干個層級使用了,因此這個屬性通常并不建議使用能用vuex的使用vuex,不能用的多傳參幾層,但是在做組件庫開發時,不對vuex進行依賴,且不知道用戶使用環境的情況下可以很好的使用
實現途徑是在要相互通信的兄弟組件之中,都引入一個新的vue實例,然后通過分別調用這個實例的事件觸發和監聽來實現通信和參數傳遞。
有了eventbus后
發送組件中
`
EventBus.$emit("hello", this.number);`
接受組件中
`
EventBus.$on("hello", (number) = > {
console.log(number)
});`
使用case
注意
$bus.on應該在created鉤子內使用,如果在mounted使用,有可能接收不到其他組件來自created鉤子內發出的事件。
使用了$bus.on,在beforeDestroy鉤子里應該再使用$bus.off解除,因為組件銷毀后,沒有必要把監聽句柄存儲在vue-bus里了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/110022.html
摘要:在他的重學前端課程中提到到現在為止,前端工程師已經成為研發體系中的重要崗位之一。大部分前端工程師的知識,其實都是來自于實踐和工作中零散的學習。一基礎前端工程師吃飯的家伙,深度廣度一樣都不能差。 開篇 前端開發是一個非常特殊的行業,它的歷史實際上不是很長,但是知識之繁雜,技術迭代速度之快是其他技術所不能比擬的。 winter在他的《重學前端》課程中提到: 到現在為止,前端工程師已經成為研...
閱讀 2474·2021-11-16 11:45
閱讀 2444·2021-10-11 10:59
閱讀 2251·2021-10-08 10:05
閱讀 3816·2021-09-23 11:30
閱讀 2370·2021-09-07 09:58
閱讀 790·2019-08-30 15:55
閱讀 773·2019-08-30 15:53
閱讀 1923·2019-08-29 17:00