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 データベースにリモートでログインする方法

推薦する

ユニークインデックスの S ロックと X ロックによる MySQL デッドロック ルーチンの理解

「初心者向けソースコードからの MySQL デッドロック問題の理解」では、MySQL ソースコードを...

Nginx レベルで基本的なユーザー認証を構成する手順を完了します。

序文アプリケーション シナリオ: おそらく、内部 Web サイトは外部ユーザーにアクセス可能である必...

ウェブサイトデザインの基礎知識:初心者の方はぜひお読みください

今では多くの人がウェブサイト作成に参加していますが、ウェブサイトはどのように作成すればよいのでしょう...

Nginx + consul + upsync を使用して動的負荷分散を実現する方法の詳細な説明

目次前提条件DNSドメイン名解決プロセス外部ネットワークマッピングnginxコア知識nginxとはア...

MySQL 5.7.20 のインストールと設定方法のグラフィック チュートリアル (win10)

この記事では、MySQL 5.7.20のインストールと設定方法を参考までに紹介します。具体的な内容は...

HTMLとCSSを使用して、自分だけの暖かい男「Dabai」を作成します

最終結果はこんな感じです、かわいいでしょう… PS: HTML と CSS の知識があればベストです...

IDEA の Maven プロジェクトで MySQL 8.0 に接続して使用する方法に関するチュートリアル

まず、私の基本的な開発環境を見てみましょう。オペレーティングシステム: MacOS 10.13.5 ...

js ドラッグ アンド ドロップ テーブルでコンテンツ計算を実現する

この記事の例では、コンテンツの計算を実現するためのjsドラッグアンドドロップテーブルの具体的なコード...

MySQLテクノロジーにおけるInnoDBロックの詳細な説明

目次序文1. ロックとは何ですか? 2. InnoDBストレージエンジンのロック2.1 ロックの種類...

Dockerデータボリューム操作の実装

データボリュームの使用開始先ほどのケースでは、ホストからコンテナにデータをコピーする必要がある場合、...

HTML/XHTML における img 画像タグの基本的な使用法の詳細な説明

画像タグは、Web ページに画像を表示するために使用されます。 HTML/XHTML 画像 <...

K8Sの5つのコントローラーの紹介と使用

目次k8sのコントローラータイプポッドとコントローラの関係デプロイメント(ステートレスアプリケーショ...

MySQL ステートメントにおける IN と Exists の比較分析

背景最近、SQL 文を書くときに、IN と Exists のどちらを選択するか迷ったので、両方の方法...

node.js で EventEmitter をカスタマイズする方法

目次序文1. 何ですか2. Node.jsでEventEmitterを使用する方法3. 実施プロセス...

HTML は CSS スタイルと JS スクリプトを動的に読み込みます。例

1. スクリプトを動的に読み込むウェブサイトの需要が高まるにつれて、スクリプトの需要も徐々に増加しま...