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

推薦する

MySQL 8.0.20 インストール チュートリアル (画像とテキスト付き) (Windows 64 ビット)

1: mysql公式サイトからダウンロードhttps://dev.mysql.com/downlo...

Vue3でカルーセルコンポーネントをカプセル化する方法

目的カルーセルコンポーネントをカプセル化して直接使用します。具体的な内容は以下のとおりです。一般的な...

CentOS 8 Zabbix 4.4 インストール ガイド

Zabbix サーバー環境プラットフォームZABBIX バージョン 4.4セントOS8 MySQL ...

Linux ファイル管理コマンド例の分析 [表示、閲覧、統計など]

この記事では、Linux ファイル管理コマンドについて例を挙げて説明します。ご参考までに、詳細は以下...

JavaScript クロージャの説明

目次1. クロージャとは何ですか? 1.2 クロージャのメモ化: 関数は定義された環境を記憶する1....

カーソル ループを使用して、MySQL ストアド プロシージャで一時テーブルを読み取る

カーソルカーソルは、結果セット内のデータを表示または処理するために使用される方法です。カーソルを使用...

上部の固定divは半透明効果に設定できます

コードをコピーコードは次のとおりです。 <!DOCTYPE html PUBLIC "...

モバイルウェブページのサイズ調整を実装する方法

ようやく手元のプロジェクトが終了し、行方不明だった人たちが戻ってきました!プロジェクトを進める過程で...

Bツリーの特性の紹介

B ツリーは一般的なデータ構造です。彼と一緒にB+ツリーがあります。ここで、概念を明確にする必要があ...

変数が空かどうかを判定するシェルの方法の概要

シェルで変数が空かどうかを判断する方法シェルプログラミングでは、パラメータのエラーチェック項目に、変...

インタラクティブな視覚化 JS ライブラリ gojs の使い方の紹介とヒント

目次1. gojsの紹介2. Gojsのアプリケーションシナリオ3. gojs を選ぶ理由: 4. ...

デジタルテーブル特殊効果を実現するネイティブJS

この記事では、ネイティブ JS で実装されたデジタル時計エフェクトを紹介します。エフェクトは次のとお...

Vue 監視属性のグラフィック例の詳細な説明

目次リスナープロパティとは何ですか?リスニングプロパティと計算プロパティの違いは何ですか?監視プロパ...

HTML でよく使用されるエスケープ文字の概要

HTML でよく使用されるエスケープ文字をまとめると次のようになります。 &nbsp; 改行...