微信小程式 關於父子元件一些心得

西瓜弟弟發表於2019-03-02

父子元件樣式的設定

1、 如何對父子元件設定flex佈局

如果在小程式中對父元件設定 display:flex 或者 display:inline-flex 然後再對子元件最外層元素的class設定flex的樣式屬性會發現不會有效果。

比如在這個截圖中

微信小程式 關於父子元件一些心得

父元素 .parent-box 是 display:flex 然後對子元素 .child-box 設定 flex、justify-content、align-content 等屬性會發現都沒有效果。

我們看截圖可以發現其實微信小程式渲染完後會對元件裡面的內容再套一層元件名稱的標籤。所以如果要對子元素設定flex屬性的話應該對子元素使用小程式提供的:host選擇器。

父元素樣式

.parent-box{
    display:flex;
}
複製程式碼

子元素樣式

:host{
    flex: 1;
}
複製程式碼

2、根據不同條件渲染子元件根節點的樣式

比如元件在某些特殊場景不使用flex佈局而是採用其他方式佈局,我們希望同過某種方式來控制子元件根節點的樣式。但是微信小程式的:host選擇器似乎沒法做到這種需求。如果後面微信小程式的:host選擇器可以支援屬性選擇器也許可以做到。

這裡沒有找到特別好的辦法,這裡我說下兩種比較差的解決方法

· 在小程式自定義元件標籤其實相對於view標籤或者text標籤可以直接在標籤中使用style或者class的。就是利用標籤的style或者class動態去改變。

<parent>
    <child 
        class="{{ childStyle == 1 ? child-style-1 : child-style-2 }}"
        style="{{ childStyle == 1 'background:red;':'background:blue' }}" >
    </child>
</parent>
複製程式碼

這裡嘗試過在父元件和子元件去設定子元件的class都是沒有反應的,所以子元件class只能在Page的Wxss中去設定。

· 一種就是如果明確了子元件的標籤名稱我們可以在父元件的樣式中去設定不同的子元件樣式

父元素樣式

.parent{
    display:flex;
}
.parent-box child{
    flex:1;
}
.parent-box.column child{
    flex-direction: column;
}
.parent-box.row child{
    flex-direction: row;
}
複製程式碼

不過這種方式也不太好,因為元件的是在Page的json可以隨意命名的,這種方法除非是團隊開發開始個人約定好了元件的名稱,不會隨意給元件起名的情況下。

這種方法甚至可以用CSS的選擇器控制某一個子元件單獨的樣式

父元素樣式

.parent-box child:first-child{
    flex:1;
}
複製程式碼

父元素獲取子元素WMXL

有些時候為了一些元件的擴充套件性我們會把他們拆成父子元件,又有些時候元件內有一些需要酷炫的樣式動畫我們可能需要在父元件內拿到子元件的節點資訊去進行計算。這裡我說下我用的方法。

1、使用 wx.createSelectorQuery().in()

在linked生命週期時會傳遞過來子元件的例項物件,在這個使用把wx.createSelectorQuery().in傳入子元件包裝成Promise插入陣列。待要獲取子元素們的節點資訊時呼叫。

微信小程式 關於父子元件一些心得

父元件JS

Component({
       data: {
           childRectPromises:[]
       },
       relations: {
           '/child': {
               type: 'child',
               linked(v) {
                   const p = ()=> new Promise((resolve,reject)=>{
                       const query = wx.createSelectorQuery().in(v)
                       query.select('.child-box').boundingClientRect(function(res){
                           resolve(res)
                       }).exec()
                   })
                   this.data.childRectPromises.push(p);
               },
           }
       },
       ready(){
           Promise.all(this.data.childRectPromises.map(p=>p())).then(res=>{
               /* 邏輯 */
           })
       }
})
複製程式碼

2、使用 >>> 選擇器

如果用上面的方法如果有10個子元素,我們就要呼叫10次的 wx.createSelectorQuery().in().select()。怎麼都感覺十分的消耗效能,如果可以使用selectAll一次性把全部子元素的節點資訊給拿到就好了。這時我們就想可以不可以

   wx.createSelectorQuery().in(父元素物件).selectAll(子元素節點)
複製程式碼

微信小程式 關於父子元件一些心得
經過我的測試,在元件已經渲染完畢有子元素的情況下,返回的是個空陣列,說明這種寫法是不行的。哪還有什麼辦法呢。

其實在微信小程式中 在selectAll/select中 提供了 >>> 這樣一個選擇器,這個選擇器可以在拿到頁面元件中對匹配到的節點。

我們只要 wx.createSelectorQuery().selectAll( 父元件 >>> 子元素節點 ) 像這麼寫我們就可以一次輕鬆拿到全部子節點啦。

微信小程式 關於父子元件一些心得
但是這裡我們這麼寫 wx.createSelectorQuery().selectAll( 父元件元素class >>> 子元素節點 )是沒有作用的,我的理解是,因為我們沒有在wx.createSelectorQuery()呼叫in方法就是相當於在Page中查詢這些元素,而不是在元件內,父元件元素class是封裝在元件內的所以查詢不到這個元素,也就返回了空陣列。

相對於頁面,如果我們用元件的標籤名,就如上面所說的元件名可以隨意起名並不是很合適,這時我們就想要是知道父元件的某個class或者id就好了,知道父元件設定了什麼class可能可能不太顯示,不過如果我們對標籤設定了id我們確可以從this從獲取到。

微信小程式 關於父子元件一些心得

這時我們成功只用一次selectAll獲取到了父元件的子元素們。不過這麼做有個缺點就是一定要設定id才行,不過為了效能優化我們可以從在父元件中做個判斷如果id為空則提示使用此元件需要設定id。

好了以上就是我在開發小程式中對父子元件的一些心得,如果大家有一些更好的辦法或者心得希望可以與我分享,謝謝各位。

相關文章