要想小程序界面好看,還原UI妹紙設計的界面,小程序自帶的組件肯定是無法滿足所有需求的。那想要還原比較炫酷好看的UI的時候就必不可少需要自定義組件了。寫過許多自定義組件了,也遇到過許多坑,這裏說一個比較頭大的坑,就是引入自定義組建的時候,使用selectComponent獲取自定義組件對象時,返回null的問題。
簡單示例
因爲這裏我們說的主要是selectComponent返回爲null的問題,其他問題先不考慮,這裏假設我有一個自定義組件QrCodeDialog,且自定義組件的代碼沒有問題(組件代碼本身的問題就不在本次討論範圍了)。
這個時候我在Main界面引用了QrCodeDialog,卻發現this.selectComponent()方法返回的null。
問題排查與分析
1.那首先最基本的就是看頁面的json引用路徑是否正確
2.看看wxml文件裏面的選擇器是否設置選擇器,比如我這裏設置的是id選擇器
(這裏提一下自定義組件使用什麼名字的標籤是由頁面的json文件中引用自定義組件時的key決定的,比如我引用的時候key定義的是qrcode_dialog,那麼在wxml文件使用的時候組件名就是qrcode_dialog,這個大家應該都知道^_^)
3.看看在頁面的js文件裏面引用的代碼
注意這個selectComponent方法裏面的參數要與wxml裏面設置的id選擇器的值相對應,比如我的用的id選擇器就用#號+id
如果檢查過後上面說的,全都沒問題的話,那多半就是wxml中自定義組件的那段代碼還沒渲染到就使用selectComponent引用了組件,這個時候的返回值肯定是null。產生這種大致就下面兩種情況。
1.wx:if屬性使用不當。
爲什麼說wx:if使用不當會導致selectComponent返回爲null呢?這裏不得不提一下wx:if與hidden屬性的區別,這兩個屬性我想大家都比較熟悉,都是用來控制顯示與隱藏的。要說有什麼區別,有些可愛的同學就會脫口而出:“wx:if條件爲true就顯示,反之則隱藏;hidden條件爲true就隱藏,反之則顯示!”。嗯,說的沒錯,這確實是最直觀最明顯的區別。但是說的並不全!他們還有一個區別,就是如果你用wx:if包裹了一段代碼,界面在渲染的時候,當wx:if的條件爲false的時候是不會渲染這段代碼的,只有wx:if的條件爲true纔會渲染這段代碼;而用hidden包裹的代碼無論條件是爲true還是false都會渲染它包裹的代碼,只不過爲true時將這段佈局隱藏了而已。
說到這個區別我想有些小可愛已經明白了。假如你的自定義組件包裹在了wx:if下,並且在你使用selectComponent獲取組件對象的時候,這個wx:if的條件還爲false,也就是說你引用的時候,頁面並沒有渲染到你的自定義組件,這時候使用selectComponent獲取的組件對象當然爲空,因爲都還沒渲染到。
舉個簡單的例子:
wxml文件
<view wx:if="{{a==1}}">
<qrcode_dialog id="vipQrcode1" />
</view>
qrcode_dialog 是我的自定義組件,使用view包裹,並使用wx:if添加條件如果a==1就顯示
js文件添加引用代碼
this.vipQrcode1 = this.selectComponent("#vipQrcode1")
console.log("第一次---this.vipQrcode1====", this.vipQrcode1)
this.setData({
a:1
})
this.vipQrcode1 = this.selectComponent("#vipQrcode1")
console.log("第二次--=this.vipQrcode1====", this.vipQrcode1)
這裏我先直接引用一次,打印一次日誌,再看看賦值a爲1之後再引用打印一次日誌,看看效果:
很顯然第一次的時候由於不滿足a==1的條件,selectComponent返回的是null,當我賦值了a=1時,這時候滿足了if條件,我再次引用就不爲空了。
我們在將wx:if換成hidden看看有什麼區別,只需要改下wxml文件的代碼:
<view hidden="{{a!=1}}">
<qrcode_dialog id="vipQrcode1" isShow="{{false}}" />
</view>
hidden的條件就是a!=1就隱藏,js還是之前的代碼,先直接引用一次,打印一次日誌,再賦值a爲1之後再引用打印一次日誌,我就不貼了,再看看日誌
很顯然當我換成了hidden之後,無論是否滿足條件selectComponent都不爲空。
說到這裏,趕緊看看你頁面的wxml文件的佈局文件,是不是將自定義組件放在了wx:if裏面包裹起來了,並且你引用的時候wx:if的條件是不是爲false。如果真的是這種情況導致的就將wx:if換成hidden就好了。
2.自定義組件所在層級太深
這個意思就是說你的自定義組件嵌套在n個view下面,理論上頁面渲染的順序應該是從外往裏,如果你的自定義組件嵌套的非常深,而這個時候你在頁面還未渲染完成的時候就開始使用selectComponent引用組件,獲取到的對象也有可能是會爲null,這個情況不會太穩定,有時候渲染的速度不一樣,出現偶爾引用成功,偶爾引用失敗的情況。當然這種情況極少出現,反正我這輩子沒遇見過。哈哈~誇張了一些,反正我是沒遇到過這種情況,不過理論上應該是存在這種情況的。如果真的遇到了這種情況,你可以沒必要急着一開始就去引用它,你也可以延遲幾秒鐘再引用,或者在你需要使用自定義組件裏的方法時再引用。
說了這麼多,其實只要記住this.selectComponent()返回爲null的情況無外乎就是兩種,要麼是引用錯誤,要麼就是未找到自定義組件節點,在發現其他情況的話我在補充。