WeChatアプレット開発で遭遇したことのない落とし穴のまとめ

WeChatアプレット開発で遭遇したことのない落とし穴のまとめ

getApp()

getApp() 関数は、アプリ インスタンスを取得するために使用されます。通常は問題はありませんが、いくつかの特殊なシナリオでは予期しないバグが発生します。
app.js の onLaunch コールバック関数で使用

// アプリ.js
アプリ({
 起動() {
  console.info(getApp(), '!!');
 }
});

この時点では undefined が出力されているのが分かりますが、これは当然です。結局のところ、まだ初期化段階であり、アプリはまだ生まれていません。コードがそれほど単純な場合は、この問題は簡単に見つかります。コード内のメソッドを呼び出すと、このメソッドが誤ってアプリ インスタンスを取得して変数を取得すると、事故が発生します。

したがって、同期の要件がない場合は、落とし穴を回避するために、onLaunch で関数を呼び出し、setTimout でラップすることができます。

// アプリ.js
アプリ({
 起動() {
  タイムアウトを設定する(() => {
   // ... 他の関数を呼び出す });
 }
});

getApp() を変数に割り当てる

js ファイルを作成します:

// a.js
const app = getApp();

エクスポート関数 checkVersion() {
 console.log('チェックしました!');
 console.info('アプリ', アプリ, '!!');
}

上記のファイルは通常は問題を引き起こしませんが、app.js にインポートすると、予期せぬ問題が発生します。

// アプリ.js
'a' から checkVersion をインポートします。

アプリ({
 起動() {
  console.log('私は元気です!');
 },
 オンショー() {
  バージョンチェック();
 }
});

このとき、app 変数が未定義であることがわかります。特にパッケージ化された一般的なライブラリの場合、通常は問題なく動作しますが、app.js で使用すると突然動作しなくなるため、この種のエラーを検出するのは難しい場合があります。

したがって、この問題を回避するには、パブリック アプリ インスタンスの共有を減らし、代わりにメソッド内で getApp() を直接使用してインスタンス オブジェクトを取得するようにしてください。グローバル変数を使用する場合は、変数を別の js ファイルに保存する方がよいでしょう。次に例を示します。

// グローバルストア.js

エクスポートデフォルト{
 ユーザー情報: null、
 isIos: 偽、
 isLaunched: false、
};
// アプリ.js
'globalStore' からストアをインポートします。

アプリ({
 起動() {
  ストアを起動します。
 },
 オンショー() {
  const { isLaunched } = getApp().store、
  console.log(起動済み);
 },
 店、
});

この方法では、モジュールをインポートすることでグローバル変数を取得できるほか、getApp().store を通じてグローバル変数を取得することもできます。

しかし、原則的には、モジュールをインポートしてグローバル変数を読み書きすることをお勧めします。結局のところ、getApp() は場合によっては undefined を返します。

ページエントリファイルの先頭に変数を定義します

ページ エントリ ファイルで変数を定義するのは一般的ですが、次のコードのように、ページ エントリ ファイルはページ インスタンスごとに独立して実行されるのではなく、1 回だけ実行されることに注意する必要があります。

// ページ/ページ/index.js
'api' から { getDetailInfo } をインポートします。
ajaxLock を false にします。

ページ({
 オンロード() {
  リモートデータを取得します。
 },
 非同期getRemoteData() {
  もし(ajaxロック){
   戻る;
  }
  ajaxロック = true;
  試す {
   getDetailInfo() を待機します。
  } キャッチ(エラー) {
   // ... エラーを処理する } finally {
   ajaxLock = false;
  }
 },
});

ページのロジックは比較的単純です。ページに入るとすぐにリモート データを要求します。見た目には問題ありません。ただし、複数のページを同時に開くと、最初のページだけがデータを要求し、後続のページはデータを要求しないことがわかります。これは、これらのページがすべて ajaxLock 変数を共有しているためです。したがって、ページの上部で変数を宣言する場合は、使用シナリオに注意する必要があります。

ページエントリファイルのデータにグローバル変数を直接割り当てる

コード上で直接:

// ページ/ページ/index.js
ページ({
 データ: {
  isIos: getApp().store.isIos、
 },
});

// アプリ.js
アプリ({
 起動() {
  SysInfo を取得します。
 },
 システム情報を取得する() {
  新しい Promise を返します ((resolve, reject) => {
   wx.getSystemInfoAsync({
    成功:解決、
    失敗: 拒否、
   });
  }).then((res) => {
   const { ストア } = getApp();
   store.isIos = res.platform.toLowerCase() === 'ios';
  });
 },
 店: {
  isIos: 偽、
 },
});

上記コードの主なロジックは、現在のデバイスが iOS かどうかを知ることです。シミュレーターで実行しているときはコードが非常に安定しているように見えますが、実際のマシンでは、isIos 変数が同期的にステータスを取得しないため、良い場合もあれば悪い場合もあります。ページエントリ関数の実行後に値が割り当てられると、ステータスの表示が正しくなくなります。
したがって、同期的に割り当てられない一部の状態については、初期化中にデータに直接値を割り当てないでください。onLoad コールバック関数で状態を割り当てるのが最適です。

wx.createSelectorQuery() と wx.createIntersectionObserver() について知らないこと

これら 2 つの関数もよく使用されます。wx.createSelectorQuery は主に要素を照会するために使用され、wx.createIntersectionObserver は要素が可視領域内にあるかどうかを処理するために使用されます。この2つの機能の問題点、一見かわいいものですが、特殊な要件を実装しているときに初めて発見しました。本当に後知恵で、知らないうちに強力になっていると感じていました。よく考えてみると恐ろしいですね...

問題を再現してみましょう。ページエントリ関数は次のように記述されます。

// ページ/ページ/index.js
インデックスを0にする

ページ({
 データ: {
  タグ: 0
 },
 オンロード() {
  (インデックス++ < 2)の場合{
   wx.navigateTo({
    URL: '/pages/page/index'
   });
  }
  this.setData({
   タグ: インデックス
  },() => {
   タイムアウトを設定する(() => {
    const { タグ } = this.data;
    定数クエリ = wx.createSelectorQuery();
    // 定数クエリ = this.createSelectorQuery();
    クエリを選択します(`.c-${タグ}`).boundingClientRect();
    クエリ.exec((res) => {
     console.log(タグ、res);
    });
   }, 2000);
  });
 }
});

<!-- テンプレート ファイル -->
<view class="c-{{tag}}">デモ</view>

複数のページを同時に開く状況をシミュレートしました。開発者ツールでは、最初の 2 ページの結果が null であることがわかります。 ! !その時、世界が崩壊していくように感じました。したがって、結局のところ wx.createSelectorQuery はグローバル関数なので、現在アクティブなウィンドウの下の wxml を照会するのではないかと思います。どうすれば解決できるでしょうか? 公式ドキュメントをめくって、虫眼鏡で小さな文字を探して、this.createSelectorQuery メソッドを見つけました。試してみると、突然問題が解決しました。もちろん、wx.createIntersectionObserver にも同じ問題があるので、ここでは説明しません。

したがって、健康上の理由から、this.createSelectorQuery と this.createIntersectionObserver を直接使用することを強くお勧めします。

上記は私がここ数年WeChatアプレットを開発する際に遭遇した落とし穴です。皆さんが再び陥らないことを祈ります~~

要約する

これで、WeChat ミニプログラム開発の落とし穴についての記事は終わりです。WeChat ミニプログラム開発の落とし穴の詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • taroを使用してWeChatアプレットを開発する際に遭遇する落とし穴のまとめ
  • Taro WeChatアプレット開発におけるEchartsの落とし穴
  • WeChatアプレット開発の章:落とし穴の記録

<<:  MySQL でのログインを取り消す

>>:  Filebeat を使用して Nginx ログを収集する方法

推薦する

MySqlサブクエリINの実装と最適化

目次IN が遅いのはなぜですか? INとEXISTSのどちらが速いでしょうか?効率を向上させるにはど...

React は antd のアップロード コンポーネントを使用してファイル フォーム送信機能を実装します (完全なコード)

私はプロジェクトを実行するために react を使い始めたばかりで、非常に未熟で完全な初心者です。私...

ドロップダウンリストのJavaScript実装

この記事の例では、ドロップダウンリストを実装するためのJavaScriptの具体的なコードを参考まで...

CSS フィルターを使用してマウスオーバー効果を記述する例

CSSフィルターを使用してマウスオーバー効果を記述する <div class="fi...

ノードをMySQLデータベースに接続する際に発生する問題と解決策

今日、MySQL の新しいバージョン (8.0.21) をインストールしましたが、ノード フレームワ...

Webサービスのリモートデバッグとタイムアウト動作原理の分析

Webサービスのリモートデバッグ.NET では、WEBSERVICE のリモート デバッグ機能はデフ...

Linux MySQL ルートパスワードを忘れた場合の解決方法

MySQL データベースを使用する際、何らかの理由で長期間 MySQL にログインしていない場合、ま...

Elasticsearchツールcerebroのインストールと使用チュートリアル

Cerebro は、Elasticsearch バージョン 5.x より前の Elasticsear...

JavaScript にはすでに Object があるのに、なぜ Map が必要なのでしょうか?

目次1. オブジェクトをマップとして扱わない1. 未定義のプロパティはプロトタイプチェーンを通じてア...

MySQL メタデータで Hive テーブル作成ステートメントのコメント スクリプトを生成する方法

序文この記事は主にMySQLメタデータ生成Hiveテーブル作成ステートメントコメントスクリプトに関す...

IE環境では、divの高さはフォントの高さよりも大きくなければならないと規定されています。

コードをコピーコードは次のとおりです。 <div class="content&qu...

DockerコンテナのIPアドレスを取得する方法の詳細な説明

1.コンテナに入った後 /etc/hosts を cat するコンテナ自体の IP アドレスと (-...

CSS で実現される HTML 背景色のグラデーション

エフェクトのスクリーンショット:実装コード:コードをコピーコードは次のとおりです。 <!DOC...

vue ルーティング ビュー router-view のネストされたジャンプの実装

目次1. app.vueページを修正する2. ログインページを作成する (/views/login/...

webpackの遅延読み込みとプリロードの詳細な説明

目次通常の読み込み遅延読み込みプリロードプリロードを使用しないプリロードの使用要約する通常の読み込み...