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

推薦する

Vueは動的に生成されたコンポーネントをドラッグアンドドロップする要件を実装します

目次製品要件アイデア問題ライブラリ選択をドラッグコンポーネントを生成する方法コンポーネントを生成する...

Linux システムの busybox に mkfs.vfat コマンドを移植する

オーディオおよびビデオ ファイルを保存するためのディスク寿命を延ばすには、ディスクをフォーマットする...

Ubuntu 18.04 のインストールで「ldlinux.c32 のロードに失敗しました」というエラーが表示され、解決手順がわかりません

序文私は Win7 を搭載した古いラップトップを持っています。古いシステムを維持しながら、同時に U...

Reactコンポーネントのライフサイクル機能についての簡単な説明

React コンポーネントのライフサイクル機能とは何ですか?ライフサイクル関数は、ES6 構文クラス...

VUE uni-app でよく使用される API についての簡単な説明

目次1. ルーティングとページジャンプ2. インターフェース要約する1. ルーティングとページジャン...

WeChatアプレットのスクロールビューが左右連動効果を実現

WeChatアプレットはスクロールビューを使用して左右のリンクを実現します。参考までに、具体的な内容...

mysql ダーティ ページとは何ですか?

目次ダーティページ(メモリページ)ダーティページが表示されるのはなぜですか?メモリ管理メカニズムの簡...

mysql5.7.19 解凍版の詳細なインストール チュートリアル (純粋なクラックされた中国語版 SQLYog を使用)

Mysql5.7.19バージョンは今年リリースされた新しいバージョンです。最近のMySQLのバージ...

レンダリング関数と JSX の詳細

目次1. 基本2. ノード、ツリー、仮想DOM 1. 仮想DOM 3. createElementパ...

Linuxのファイル権限の詳細な紹介

Linux の優れた点は、マルチユーザー、マルチタスク システムにあります。 Linux では通常、...

Ansible を使用した Nginx のバッチ デプロイのサンプル コード

1.1 nginxインストールパッケージとインストールスクリプトをクライアントにコピーし、スクリプト...

Linux での SSH 非秘密通信の実装

SSHとは何か管理者はリモートでログインして、インターネット経由で接続されたさまざまな場所にある複数...

動的テーブルを実装するための要素サンプルコード

目次【コード背景】 【コード実装】 #1# -> コード再利用の基本は、再利用可能なコンポーネ...

MySQL 最適化の概要 - クエリエントリの合計数

1. COUNT(*) と COUNT(COL) COUNT(*)は通常、主キーに対してインデックス...

Ubuntu 20.04にvncserverをインストールする方法

Ubuntu 20.04は2020年4月に正式にリリースされました。本日、ミラーシステムを正式にイン...