現(xiàn)在我們已經(jīng)可以做到了兩個組件之間的數(shù)據(jù)傳遞,那么如何在多個組件間傳遞數(shù)據(jù)呢?
如上圖所示,同級的組件b 和同級的組件c , b 和 c 之間不可以直接獲取,b可以獲取到a, c 也可以獲取到a,而a可以直接獲取到 b 和 c。所以,如果想獲取到兄弟元素,需要先獲取到祖先節(jié)點,然后再通過祖先節(jié)點獲取兄弟節(jié)點 我在組件b 里面,我需要先找到祖先組件a的實例,然后用祖先組件a的實例的getRelationNodes方法獲取到組件c的實例。? 看見沒?恐怕我們又要寫一大堆重復性的代碼了。
幸好,微信小程序還提供了behavior 屬性, 這個屬性相當于 mixin,很容易理解的,是提高代碼復用性的一種方法。 思路:
實現(xiàn): 新建一個behavior文件,命名無所謂,比如說relation_behavior.js // 在 get_relation.js 文件里面 module.exports = Behavior({ methods:{ // 獲取父組件實例的快捷方法 _parent () { // 如果根據(jù)該路徑獲取到acestor組件為null,則說明this為ancesor var parentNode = this.getRelationNodes('../record_item/record_item') if (parentNode&&parentNode.length !== 0) { return parentNode[0] } else { return this } }, // 獲取兄弟組件實例的快捷方法 _sibling(name) { var node = this._parent().getRelationNodes(`../${name}/${name}`) if (node &&node.length > 0) { return node[0] } } } }) 然后在組件b, 和 組件c 上引入該behavior,并且調(diào)用方法,獲取父組件和兄弟組件的實例 // 組件b中 var relation_behavior = require('./path_to_relation_behavior') Component({ behaviors:[relation_behavior], methods:{ test () { // 獲得父組件的實例 let parent = this._parent() // 訪問父組件的數(shù)據(jù)d console.log(parent.data.name) // 修改父組件的數(shù)據(jù) parent.setData({ name: 'test1' }) // 獲得兄弟組件的實例 let sibling = this._sibling('c') // 訪問兄弟組件的數(shù)據(jù) console.log(sibling.data.name) // 修改兄弟組件的數(shù)據(jù) sibling.setData({ name:"test" }) } } }) // 組件c中 var relation_behavior = require('./path_to_relation_behavior') Component({ behaviors:[relation_behavior], methods:{ test () { // 獲得父組件的實例 let parent = this._parent() // 訪問父組件的數(shù)據(jù)d console.log(parent.data.name) // 修改父組件的數(shù)據(jù) parent.setData({ name: 'test1' }) // 獲得兄弟組件的實例 let sibling = this._sibling('b') // 訪問兄弟組件的數(shù)據(jù) console.log(sibling.data.name) // 修改兄弟組件的數(shù)據(jù) sibling.setData({ name:"test" }) } } })
同時需要注意,c和b兩個組件,從relations屬性的角度來說,是a的后代組件。 但是組件b和組件c 所處的作用域, 都是主頁面的作用域,傳入的property都是主頁面的property,這樣就保證了組件數(shù)據(jù)的靈活性。relations 像一個隱形的鏈子一樣把一堆組件關(guān)聯(lián)起來,關(guān)聯(lián)起來的組件可以相互訪問,修改對方的數(shù)據(jù),但是每一個組件都可以從外界獨立的獲取數(shù)據(jù)。
看了這么多理論的東西,還是需要一個具體的場景來應用。 比如說,我們有個一個分享記錄圖片心情的頁面,當用戶點擊【點贊】的按鈕時候,該心情的記錄 點贊按鈕會變紅,下面的一欄位置會多出點贊人的名字。
如果不通過組件化,很可能的做法是 修改一個點贊按鈕,然后遍歷數(shù)據(jù)更新數(shù)據(jù),最后所有記錄列表的狀態(tài)都會被重新渲染一遍。 如果是通過組件化拆分:把點贊的按鈕封裝為 組件b, 下面點贊人的框封裝為組件c, 每一個心情記錄都是一個組件a 下面是代碼實現(xiàn) // 在主頁面內(nèi) <view wx:for='{{feed_item}}'> <a item='{{item}}'> <b></b> <c></c> </a> <view> // 在組件a內(nèi) var behavior_relation = require('../../relation_behavior.js) //這里引入上文說的Behavior Component({ behaviors:[behavior_relation], relations:{ '../b/b':{ type: 'descendant' } } }) // 在組件b內(nèi) var behavior_relation = require('../../relation_behavior.js) //這里引入上文說的Behavior Component({ behaviors:[behavior_relation] relations:{ '../a/a':{ type: 'ancestor' } }, data: { is_like: false //控制點贊圖標的狀態(tài) }, methods:{ // 當用戶點贊的時候 onClick () { // 修改本組件的狀態(tài) this.setData({ is_like: true }) // 修改 c 組件的數(shù)據(jù) this._sibling('c').setData({ likeStr: this._sibling('c').data.likeStr + '我' }) } } }) // 在組件c內(nèi) var behavior_relation = require('../../relation_behavior.js) //這里引入上文說的Behavior Component({ behaviors:[behavior_relation], relations:{ '../a/a':{ type: 'ancestor' } }, data:{ likeStr:'曉紅,小明' } }) 這樣,組件b 可以修改組件c中的數(shù)據(jù)。同時,組件b 和 組件c 又可以通過 properties 和 事件系統(tǒng),和主頁面保持獨立的數(shù)據(jù)通信。 |
工作日 8:30-12:00 14:30-18:00
周六及部分節(jié)假日提供值班服務