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

推薦する

Docker: /etc/default/docker の DOCKER_OPTS パラメータを変更しても反映されない

デフォルトでは、 /etc/default/docker 設定は有効になりません。docker 環境...

MySQLのインデックス選択と最適化の詳細な説明

目次インデックスモデルB+ツリーインデックスの選択インデックスの最適化インデックスの選択性カバーイン...

Mysql sql スロークエリ監視スクリプトコード例

1. my.cnfを変更する #全体的な効果としては、グローバルがオンになっている場合はテーブルとロ...

WeChatアプレットが左右連携を実現

この記事では、WeChatアプレットの左右連動を実現するための具体的なコードを参考までに紹介します。...

現在のマウススライドの座標を取得するVue+openlayer5メソッド

序文: Vue プロジェクトで現在のマウスの座標を取得するにはどうすればよいでしょうか。ここで共有す...

Docker を使用した nextcloud パーソナル ネットワーク ディスクの構築に関するチュートリアル

目次1. はじめに2. 導入環境ツール4. 展開プロセス要約する1. はじめにNextcloud は...

mysqlとnavicat間の接続を確立する際の1251エラーを解決する

コンピュータを再インストールし、最新バージョンのMySQLデータベースをインストールしました。その結...

MySQL 検査スクリプト (必読)

以下のように表示されます。 #!/usr/bin/env python3.5 psutilをインポー...

Dockerイメージを素早くデプロイして実行する最新のIDEAプロセスの詳細な説明

背景docker とアイデアを使用して、Java Web の開発、展開、運用までのプロセス全体を実現...

JS+Canvas でダイナミックな時計効果を実現

参考までに、Canvas をベースにしたダイナミッククロックのデモを用意しました。具体的な内容は次の...

CSS3で実装された6つの境界遷移効果

6つの効果実装コードhtml <h1>CSS 境界遷移</h1> <セ...

Dockerコンテナ内のホストのホスト名が取得できない問題の解決方法

Node.js環境でテストが通っています。他の言語でも同様です。環境変数を取得する方法を使うだけです...

MYSQLデータベーステーブル構造の最適化方法の詳細な説明

この記事では、例を使用して、MYSQL データベース テーブル構造を最適化する方法を説明します。ご参...

uniapp 要素ノードスタイルの動的変更の詳細な説明

目次1. スタイル属性をバインドして変更するhtml:対応するjs:達成された効果:次に、refを使...

HTML から PDF への変換事例の概要 (複数の画像を推奨)

仕事の都合上、最近 HTML を PDF に変換する機能について調べることに時間を費やしました。 H...