溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

微信小程序組件的生命周期有哪些

發(fā)布時(shí)間:2021-03-03 15:32:13 來源:億速云 閱讀:776 作者:Leah 欄目:開發(fā)技術(shù)

微信小程序組件的生命周期有哪些?很多新手對此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

組件 attached 生命周期執(zhí)行次數(shù)

按照通常的理解,除moved/show/hide等生命周期可能多次執(zhí)行外,

嚴(yán)格意義上與組件加載相關(guān)的生命周期,如:created、attached、ready等,每個(gè)組件實(shí)例應(yīng)該只執(zhí)行一次。但是事實(shí)真的如此嗎?

背景

這個(gè)問題的發(fā)現(xiàn),源于我們在小程序的報(bào)錯(cuò)日志中,

收到大量類似Cannot redefine property: isComponent的報(bào)錯(cuò)。

微信小程序組件的生命周期有哪些

原因分析

通過變量名可以追溯到我們在代碼中的定義方式為:

Component({
 lifetimes: {
 attached() {
 Object.defineProperty(this, 'isComponent', {
 enumerable: true,
 get() { return true },
 });
 },
 },
});

很容易理解,這種錯(cuò)誤的起因在于試圖給對象重新定義一個(gè)不可配置的屬性,

具體可以查看MDN上的說明。

可是這個(gè)定義是寫在attached生命周期當(dāng)中的,難道說,組件的attached生命周期被觸發(fā)了兩次?

天吶,這怎么可能?

是的,就是這么神奇!

場景還原

該問題并不容易復(fù)現(xiàn),但是通過不斷刪繁就簡、抽絲剝繭,最終還是找到了問題的根源:

在頁面onLoad之前,通過setData改變狀態(tài)觸發(fā)子組件渲染,該子組件的attached生命周期會被觸發(fā)兩次。

微信小程序組件的生命周期有哪些

可以通過以下代碼復(fù)現(xiàn)該場景,或者直接訪問小程序代碼片段。

頁面

// page.js
Page({
 data: {
 showChild2: false,
 },
 onChild1Attached() {
 this.setData({ showChild2: true });
 },
});
<!-- page.wxml -->
<child1 bind:attached="onChild1Attached"></child1>
<child2 wx:if="{{ showChild2 }}"></child2>

子組件1

與頁面一同渲染,并在attached的時(shí)候,通過triggerEvent,通知頁面更新狀態(tài)并渲染子組件2。

// child1.js
Component({
 lifetimes: {
 attached() {
 this.triggerEvent('attached');
 },
 },
});
<!-- child1.wxml -->
<view>child1</view>

子組件2

執(zhí)行了兩次attached生命周期,導(dǎo)致報(bào)錯(cuò)。

// child2.js
Component({
 lifetimes: {
 attached() {
 Object.defineProperty(this, 'isComponent', {
 enumerable: true,
 get() { return true },
 });
 },
 },
});
<!-- child2.wxml -->
<view>child2</view>

組件 ready 生命周期的執(zhí)行時(shí)機(jī)

小程序官方文檔沒有明確給出組件生命周期的執(zhí)行順序,不過通過打印日志我們可以很容易地發(fā)現(xiàn):

  • 在加載階段,會依次執(zhí)行:created -> attached -> ready

  • 在卸載階段,會依次執(zhí)行:detached

所以,看起來這個(gè)順序貌似應(yīng)該是:created -> attached -> ready -> detached。

但是實(shí)際情況果真如此嗎?

背景

有段時(shí)間,客服經(jīng)常反饋,我們的小程序存在串?dāng)?shù)據(jù)的現(xiàn)象。

例如:A商家的直播展示了B商家的商品。

原因分析

串?dāng)?shù)據(jù)發(fā)生在多個(gè)場景,考慮到數(shù)據(jù)是通過消息推送到小程序端上的,最終懷疑問題出在WebSocket通信上。

在小程序端,我們封裝了一個(gè)WebSocket通信組件,核心邏輯如下:

// socket.js
Component({
 lifetimes: {
 ready() {
 this.getSocketConfig().then(config => {
 this.ws = wx.connectSocket(config);
 this.ws.onMessage(msg => {
 const data = JSON.parse(msg.data);
 this.onReceiveMessage(data);
 });
 });
 },
 detached() {
 this.ws && this.ws.close({});
 },
 },
 methods: {
 getSocketConfig() {
 // 從服務(wù)器請求 socket 連接配置
 return new Promise(() => {});
 },
 onReceiveMessage(data) {
 event.emit('message', data);
 },
 },
});

簡單說,就是在組件ready時(shí),初始化一個(gè)WebSocket連接并監(jiān)聽消息推送,然后在detached階段關(guān)閉連接。

看起來并沒有什么問題,那么就只能從結(jié)果倒推可能不符合常理的情況了。

數(shù)據(jù)串了 -> WebSocket 消息串了 -> WebSocket 沒有正常關(guān)閉 -> close有問題/detached未執(zhí)行/ready在detached之后執(zhí)行

場景還原

此處的實(shí)際業(yè)務(wù)邏輯較為復(fù)雜,因此只能通過簡化的代碼來驗(yàn)證。

通過不斷試驗(yàn),最終發(fā)現(xiàn):

組件的 ready 與 detached 執(zhí)行順序并沒有明確的先后關(guān)系。

微信小程序組件的生命周期有哪些

可以通過以下代碼復(fù)現(xiàn)該場景,或者直接訪問小程序代碼片段。

頁面

// page.js
Page({
 data: {
 showChild: true,
 },
 onLoad() {
 this.setData({ showChild: false });
 },
});
<!-- page.wxml -->
<child wx:if="{{ showChild }}" />

組件

組件未ready的時(shí)候銷毀組件,會先同步執(zhí)行detached,然后異步執(zhí)行ready。

// child.js
Component({
 lifetimes: {
 created() {
 console.log('created');
 },
 attached() {
 console.log('attached');
 },
 ready() {
 console.log('ready');
 },
 detached() {
 console.log('detached');
 }
 },
});

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI