WeChatアプレットコンポーネントライフサイクルの落とし穴の記録

WeChatアプレットコンポーネントライフサイクルの落とし穴の記録

通常、コンポーネントのライフサイクルは、ビジネス ロジックが始まる場所です。

ビジネスシナリオが複雑でコンポーネントのライフサイクルが期待通りに機能しない場合は、

これにより、再現や修正が非常に難しい奇妙なビジネス バグが発生する可能性があります。

コンポーネント添付ライフサイクル実行時間

一般的な理解によれば、複数回実行される可能性のある移動/表示/非表示のライフサイクルを除いて、

厳密に言えば、作成、アタッチ、準備完了などのコンポーネントの読み込みに関連するライフサイクルは、各コンポーネント インスタンスに対して 1 回だけ実行される必要があります。しかし、これは本当にそうなのでしょうか?

背景

この問題の発見は、ミニプログラムのエラー ログから得られました。

「プロパティ: isComponent を再定義できません」などのエラーが多数発生しました。

原因分析

変数名を通じて、コード内での定義方法を遡ることができます。

成分({
 生涯:
 添付() {
 Object.defineProperty(this, 'isComponent', {
 列挙可能: true、
 get() { true を返す },
 });
 },
 },
});

このエラーの原因は、オブジェクトの構成不可能なプロパティを再定義しようとしていることであることは容易に理解できます。

詳細については、MDN の説明を参照してください。

しかし、この定義は添付ライフサイクル内に記述されています。コンポーネントの添付ライフサイクルが 2 回トリガーされることを意味しますか?

ああ、なんてことだ、どうしてこんなことが可能なのか?

はい、それは魔法のようです!

シーンの復元

この問題を再現するのは簡単ではありませんが、問題を継続的に単純化して解明することで、最終的に根本的な原因を見つけました。

ページが onLoaded になる前に、setData を介して状態を変更することでサブコンポーネントのレンダリングがトリガーされ、サブコンポーネントの添付ライフサイクルが 2 回トリガーされます。

このシナリオは次のコードで再現することも、アプレット コード スニペットに直接アクセスすることもできます。

ページ

// ページ.js
ページ({
 データ: {
 表示子2: false、
 },
 onChild1Attached() {
 this.setData({ showChild2: true });
 },
});

<!-- page.wxml -->
<child1 バインド:添付="onChild1Attached"></child1>
<child2 wx:if="{{ showChild2 }}"></child2>

サブコンポーネント 1

ページと一緒にレンダリングされ、アタッチされると、ページにステータスを更新し、triggerEvent を通じてサブコンポーネント 2 をレンダリングするように通知します。

//child1.js
成分({
 生涯:
 添付() {
 this.triggerEvent('添付');
 },
 },
});

<!-- child1.wxml -->
<view>子1</view>

サブコンポーネント 2

添付されたライフサイクルが 2 回実行され、エラーが発生しました。

//child2.js
成分({
 生涯:
 添付() {
 Object.defineProperty(this, 'isComponent', {
 列挙可能: true、
 get() { true を返す },
 });
 },
 },
});
<!-- child2.wxml -->
<view>子2</view>

コンポーネント準備ライフサイクル実行時間

ミニプログラムの公式ドキュメントでは、コンポーネントのライフサイクルの実行順序は明確に示されていませんが、ログを印刷することで簡単に確認できます。

  • 読み込みフェーズでは、作成済み -> アタッチ済み -> 準備完了の順に以下の手順が実行されます。
  • アンインストールフェーズでは、次の操作が順番に実行されます。

したがって、順序は、作成済み -> アタッチ済み -> 準備完了 -> デタッチ済みである必要があるようです。

しかし、これは本当にそうなのでしょうか?

背景

一時期、当社のミニプログラムにデータの文字列化があるという報告がカスタマー サービスから頻繁にありました。

例: 販売者 A のライブ放送では、販売者 B の製品が紹介されます。

原因分析

文字列データは複数のシナリオで発生します。データがメッセージ経由でミニプログラムにプッシュされることを考慮すると、最終的には WebSocket 通信に問題があると疑われます。

ミニプログラム側では、WebSocket 通信コンポーネントをカプセル化します。コアロジックは次のとおりです。

// ソケット.js
成分({
 生涯:
 準備ができて() {
 this.getSocketConfig().then(config => {
 this.ws = wx.connectSocket(config);
 this.ws.onMessage(メッセージ => {
 定数データ = JSON.parse(msg.data);
 this.onReceiveMessage(データ);
 });
 });
 },
 切り離された() {
 this.ws && this.ws.close({});
 },
 },
 メソッド: {
 getSocketConfig() {
 // サーバーにソケット接続構成を要求します。 return new Promise(() => {});
 },
 onReceiveMessage(データ) {
 イベント.emit('メッセージ', データ);
 },
 },
});

簡単に言うと、コンポーネントの準備が整うと、WebSocket 接続が初期化され、メッセージのプッシュがリッスンされ、その後、接続がデタッチ フェーズで閉じられます。

問題はないようですから、結果からは常識に沿わないかもしれない状況を推測することしかできません。

データの順序が正しくない -> WebSocket メッセージの順序が正しくない -> WebSocket が適切に閉じられていない -> close が間違っている/detached が実行されていない/detached 後に ready が実行される

シーンの復元

ここでの実際のビジネス ロジックは比較的複雑なので、簡略化されたコードを通じてのみ検証できます。

継続的な実験を通じて、私たちは最終的に次のことを発見しました。

コンポーネントの準備完了とデタッチが実行される明確な順序はありません。

このシナリオは次のコードで再現することも、アプレット コード スニペットに直接アクセスすることもできます。

ページ

// ページ.js
ページ({
 データ: {
 表示子: true、
 },
 オンロード() {
 this.setData({ showChild: false });
 },
});

<!-- page.wxml -->
<child wx:if="{{ showChild }}" />

コンポーネント

コンポーネントが準備ができていないときに破棄されると、まず detached が同期的に実行され、次に ready が非同期的に実行されます。

//child.js
成分({
 生涯:
 作成された() {
 console.log('作成されました');
 },
 添付() {
 console.log('添付');
 },
 準備ができて() {
 console.log('準備完了');
 },
 切り離された() {
 console.log('デタッチ');
 }
 },
});

拡大する

初期化作業が準備段階から接続段階に移動されたとしても、非同期操作がある限り、非同期コールバックの前にデタッチが実行される可能性があります。

したがって、コンポーネントのデタッチフェーズ中の破壊操作を完全に信頼しないでください。

要約する

WeChatミニプログラムコンポーネントライフサイクルの落とし穴に関するこの記事はこれで終わりです。ミニプログラムコンポーネントライフサイクルに関するより関連性の高いコンテンツについては、123WORDPRESS.COMで以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後も123WORDPRESS.COMを応援していただければ幸いです。

以下もご興味があるかもしれません:
  • WeChatアプレットのスクロールビューの水平スクロールの実際的な落とし穴とスクロールバーを非表示にする実装の詳細な説明
  • WeChatアプレットはnpmサポートを使用して穴に足を踏み入れる
  • WeChatミニプログラムスロットの落とし穴への解決策
  • WeChatアプレットの落とし穴記録:tabBar.list[3].selectedIconPathのサイズが40kbを超える問題を解決
  • WeChatアプレットnpmにvant-weappを導入する際の落とし穴
  • WeChatアプレットカスタムタブバーステップ練習記録
  • Taro WeChatアプレット開発におけるEchartsの落とし穴
  • WeChatアプレットフレームワークwepyの落とし穴の詳細な説明(vueと比較)
  • WeChatアプレット開発の章:落とし穴の記録

<<:  Linux でマウントされたファイルシステムの種類を表示する方法

>>:  MySQL 5.1 のパスワードを変更し、MySQL データベースにリモートでログインする方法

推薦する

react+antd.3x は IP 入力ボックスを実装します

この記事では、IP入力ボックスを実装するための react+antd.3x の具体的なコードを参考ま...

CSS変数がJSインタラクティブコンポーネント開発にもたらす改善と変更のサンプルコードの詳細な説明

1. CSS変数がもたらす質的変化CSS 変数によってもたらされる改善は、CSS コードの節約や C...

Zabbix はどのようにして ssh 経由でネットワーク デバイス データを監視および取得するのでしょうか?

シナリオシミュレーション:ある会社の運用保守担当者は、以前購入した一連のネットワーク機器の光ポートの...

MySQL 5.7.18 インストーラーのインストール ダウンロード グラフィック チュートリアル

この記事では、MySQL 5.7.18インストーラーの詳細なインストールチュートリアルを参考までに記...

JavaScriptで継承を実装するいくつかの方法

目次構造継承(callで実装)プロトタイプチェーン継承(プロトタイプチェーンの助けを借りて実装)複合...

Linux でのマルチスレッドおよびマルチプロセス クラッシュのシミュレーションに関する簡単な説明

結論:マルチスレッド環境では、スレッドの 1 つがクラッシュすると、他のスレッド (プロセス全体) ...

Azure Container Registry を使用してイメージを保存する際の問題

Azure Container Registry は、Docker Registry 2.0 仕様に...

CSSオーバーフローメカニズムについての簡単な説明

CSS オーバーフローのメカニズムを詳細に学ぶ必要があるのはなぜですか?実際の開発プロセスでは、コン...

Vue の一般的な問題と解決策の概要 (推奨)

Vue に限定されず、他の種類の SPA プロジェクトにも当てはまる問題がいくつかあります。 1....

Redhat 7.3 に MySQL 8.0.22 をインストールするための詳細なチュートリアル (バイナリ インストール)

目次1. MySQLインストールパッケージをダウンロードする2. MySQLのアンインストール手順3...

優れたウェブフロントエンドデザインの指標

Web ページのアクセシビリティは、フロントエンドでのみ評価および実装できるもののようです。ユーザビ...

MySQL InnoDBセカンダリインデックスのソート例の詳細な説明

ソート問題最近、Geek Time の「45 Lectures on MySQL Practice」...

CSS で縦書きテキスト配置を実装する方法 (概要)

HTML でのテキストのデフォルトの配置は水平ですが、特殊な場合にはテキストを垂直に配置する必要が...

LinuxでRPMを使用してmysql5.7.17をインストールする

LinuxでのMySQL5.7 rpmのインストール方法を参考までに記録します。具体的な内容は以下の...