Vue のスロットリング関数使用時の落とし穴ガイド

Vue のスロットリング関数使用時の落とし穴ガイド

序文

一般的なビジネス シナリオでは、検索ボックスへの入力が完了した後、検索データを取得するために関連リクエストを送信する必要があります。頻繁にイベントがトリガーされると、インターフェース要求が頻繁に発生しすぎます。したがって、リソースの無駄を避けるために、不必要なリクエストを禁止するようにこれを制限する必要があります〜

ビジネスシナリオを例に挙げましょう

コンセプト:

手ぶれ補正機能の紹介

addEventListenerについて

使用例:

    関数デバウンス(fn) {
        let timeout = null; // タイマーの戻り値を格納するマーカーを作成する return function () {
            clearTimeout(timeout); // ユーザーが入力するたびに、以前のsetTimeoutをクリアします。timeout = setTimeout(() => {
                // 次に、新しい setTimeout を作成します。これにより、入力文字の後の間隔内にさらに入力があった場合、fn 関数は実行されません。fn.apply(this, arguments);
            }, 500);
        };
    }
    関数 sayHi() {
        console.log('手ぶれ補正成功');
    }

    var inp = document.getElementById('inp');
    inp.addEventListener('input', debounce(sayHi)); // 手ぶれ防止

Vue で使用しますか?

まず、私が以前陥った落とし穴についてお話しします。

次のコードはシーンの簡略版です

関数デバウンス(fn) {
        let timeout = null; // タイマーの戻り値を格納するマーカーを作成する return function () {
            clearTimeout(timeout); // ユーザーが入力するたびに、以前のsetTimeoutをクリアします。timeout = setTimeout(() => {
                // 次に、新しい setTimeout を作成します。これにより、入力文字の後の間隔内にさらに入力があった場合、fn 関数は実行されません。fn.apply(this, arguments);
            }, 500);
        };
   }

間違った使い方

<テンプレート>
    <div class="検索ビュー">
        <div class="header">
            <検索 
                クラス="検索ボックス" 
                v-model='検索値' 
                @input = '検索結果を取得' 
                placeholder='欲しいものを探す' />
            <span @click="goBack" class="cancel">キャンセル</span>
        </div>
        <div class="serach-view-content" />
    </div>

</テンプレート>

<スクリプト>
'./components/Search' から Search をインポートします。
'./config' から debounce をインポートします。

エクスポートデフォルト{
    名前: 'SearchView',
    コンポーネント:
        検索
    },
    データ() {
        戻る {
            検索値: ''
        };
    },
    メソッド: {
        検索結果を取得する() {
            デバウンス(関数() {
                console.log(this.searchValue);
            })();
        }
    }
};
</スクリプト>

なぜ間違っているのでしょうか?

ソースコードレベルの分析

Vue テンプレートのコンパイル解析イベント

エクスポート const onRE = /^@|^v-on:/
エクスポート const dirRE = /^v-|^@|^:/

関数 processAttrs(el) {
  定数リスト = el.attrsList
  let i、l、名前、値、修飾子
  (i = 0, l = list.length; i < l; i++) の場合 {
    名前 = リスト[i].名前
    値 = リスト[i].値
    if (dirRE.test(名前)) {
      // 修飾子の解析 modifiers = parseModifiers(name)
      if (修飾子) {
        名前 = 名前.replace(modifierRE, '')
      }
      if (onRE.test(name)) { // v-on
        名前 = 名前.replace(onRE, '')
        addHandler(el、名前、値、修飾子、false、warn)
      }
    }
  }
}

概要: インスタンス初期化フェーズ中に呼び出される初期化イベント関数 initEvents は、実際には、テンプレートで v-on または @ を使用して親コンポーネントによって登録されたリスナー子コンポーネントでトリガーされるイベントを初期化します。

Vueのイベントメカニズム

Vue.prototype.$on = 関数(イベント、fn) {
    定数 vm = this;
    if (Array.isArray(イベント)) {
        (i = 0 とします; i < イベントの長さ; i++) {
            this.$on(イベント[i], fn);
        }
    } それ以外 {
        // この _events 属性は、現在のインスタンスのイベント センターとして使用されます。このインスタンスにバインドされたすべてのイベントは、イベント センターの _events 属性に保存されます。
        (vm._events[イベント] || (vm._events[イベント] = [])).push(fn);
    }
    vm を返します。
};

Vue.prototype.$emit = 関数(イベント) {
    定数 vm = this;
    cbs = vm._events[イベント]とします。
    もし(CBS){
        cbs = cbs.length > 1 ? toArray(cbs): cbs;
        args = toArray(引数, 1);
        (i = 0 とします; i < cbs.length; i++) {
            試す {
                cbs[i].apply(vm, args);
            } キャッチ (e) {
                handleError(e, vm, `"${event}" のイベント ハンドラー`);
            }
        }
    }
    vm を返します。
};

initMethodsメソッドはvueのinitStateで呼び出されます

initMethodsでは、メソッドメソッドをこれに掛けます

for (const キー in メソッド) {
        process.env.NODE_ENV !== 'production' の場合 {
            if (メソッド[キー] == null) {
                警告(
                    `メソッド "${key}" にはコンポーネント定義内の未定義の値があります。` +
                        「関数を正しく参照しましたか?」
                    仮想
                );
            }
            // 名前がprops内のプロパティ名と同じ場合は例外がスローされます if (props && hasOwn(props, key)) {
                warn(`メソッド "${key}" はすでにプロパティとして定義されています。`, vm);
            }
            /*
            インスタンス vm に methods 内のメソッド名が既に存在し、メソッド名が _ または $ で始まる場合、例外がスローされます。
            メソッド名が標準化されていないことをユーザーに通知する*/
            if (キーがVM内にあり、isReserved(キー)) {
                警告(
                    `メソッド "${key}" は既存の Vue インスタンス メソッドと競合します。` +
                        「_ または $ で始まるコンポーネント メソッドの定義は避けてください。」
                );
            }
            // メソッドをインスタンス vm にバインドして、this.xxx を通じてアクセスできるようにします // 同時に、vue で let m1 = this.xxx m1() とすると、this も vue を指します
            vm[key] = methods[key] == null ? noop : bind(methods[key], vm);
        }

要点:

  • サブコンポーネント $emit('input event')
  • 親コンポーネントがイベントを受信する
getSearchResult.apply(this、agrs) を実行します。
<===> apply の呼び出しは次のように記述できます。this.getSearchResult(args)

// そして、この実行は debounce(function() { になります。
      console.log(this.searchValue);
})();

// ここで debounce は関数を返すので、(function (fn) {
      clearTimeout(timeout); // ユーザーが入力するたびに、以前のsetTimeoutをクリアします。timeout = setTimeout(() => {
          // 次に、新しい setTimeout を作成します。これにより、入力文字の後の間隔内にさらに入力があった場合、fn 関数は実行されません。fn.apply(this, arguments);
      }, 500);
})()
// この時点で、実際には匿名関数の自己実行になります // 入力がトリガーされるたびに、新しい匿名関数が返されて新しい関数実行スタックが生成されるため、手ぶれ防止機能は失敗します〜

では、どう呼べばいいのでしょうか

<テンプレート>
    <div class="検索ビュー">
        <div class="header">
            <検索
                クラス="検索ボックス"
                v-model='検索値'
                @input = 'getSearchResult()'
                placeholder='欲しいものを探す'
            />
            <span
                @click="戻る"
                class="cancel">キャンセル</span>
        </div>
        <div class="serach-view-content">
            
        </div>
    </div>

</テンプレート>

<スクリプト>
'lodash.debounce' から debounce をインポートします。
エクスポートデフォルト{
    名前: 'SearchView',
    コンポーネント:
        検索、
    },
    データ() {
        戻る {
            検索値: ''、
        };
    },
    メソッド: {
        getSearchResult:デバウンス(関数() {
            console.log(this.searchValue);
        }, 500),
    },

};
</スクリプト>

実行プロセスを分析する

getSearchResult().apply(this, args)
<===> パラメータの動作を無視し、実行スタックのみに焦点を当てる let func = function () {
    clearTimeout(timeout); // ユーザーが入力するたびに、以前のsetTimeoutをクリアします。timeout = setTimeout(() => {
        // 次に、新しい setTimeout を作成します。これにより、入力文字の後の間隔内にさらに入力があった場合、fn 関数は実行されません。fn.apply(this, arguments);
    }, 500);
};

this.func(引数)

<===>

入力をトリガーするサブコンポーネントの動作は常に同じ関数本体を返します。アンチシェイクは成功します。

記事の冒頭で紹介したaddEventListenerと同様

要約する

これで、Vue でスロットリング関数を使用する際の落とし穴に関するこの記事は終わりです。Vue でスロットリング関数を使用する際の落とし穴に関する関連コンテンツの詳細については、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • VUE の手ぶれ補正とスロットリングの最適なソリューションに関する簡単な説明 (機能コンポーネント)
  • Vueカスタムディレクティブを使用してスロットリング関数をカプセル化する方法の例
  • Vueは入力ボックスのファジークエリのサンプルコードを実装します(スロットリング機能の適用シナリオ)
  • Vue における機能アンチシェイクスロットリングの理解と応用
  • Vue コンポーネントのスロットリング機能が失敗する原因と解決策

<<:  Centos 7 sshd の変更 | ルートログインの禁止と sshd ポートスクリプトの定義

>>:  MySQL データのバックアップと復元のサンプル コード

推薦する

HTML ul および li タグを使用して画像を表示するサンプル コード

以下のコードをDreamweaverのコードエリアにコピーすると、プレビュー時に以下の画像が表示され...

Gitlab実践チュートリアルでは、関連する設定操作にgit configを使用します。

この記事では、実際に発生した問題をもとに、git の設定に関する内容を紹介します。コマンド: git...

VMware10 での CentOS 7 のインストールと設定のチュートリアル

Ubuntu が今日のデスクトップ ユーザーの間で最も人気のある Linux オペレーティング シス...

IDEA を使用して Web プロジェクトを作成し、Tomcat に公開する方法

目次ウェブ開発1. Web開発の概要Tomcatのインストールと設定Tomcatをインストールする2...

JavaScript シングルスレッドと非同期の詳細

目次1. タスクキュー2. 混乱を招く問題を説明する1. setTimeout(f1,0)とは何です...

jsは動的にテーブルを生成します(ノード操作)

この記事の例では、テーブルを動的に生成するjsの具体的なコードを参考までに共有しています。具体的な内...

Raspberry Pi 4 に Ubuntu 19.10 をインストールするための詳細なチュートリアル

以前、raspbian で実行したときに opencv の一部の依存関係をパッケージ化できず、一部の...

Web開発で使用される基本的な概念と技術の紹介

本日は、Web 開発で使われる基本的な概念と技術を初心者向けに紹介します。A から Z まで合計 2...

JavaScript のプライベート クラス フィールドと TypeScript のプライベート修飾子の詳細な説明

目次JavaScript のプライベート クラス フィールドとプライバシーの必要性JavaScrip...

ハイパーリンクを使用してリンクファイルを開く HTML 方式の紹介

a および href 属性 HTML では、英語ではアンカーと呼ばれるハイパーリンクを表すために &...

PHPのmail()関数を使用してメールを送信する

PHPのメール関数を使用してメールを送信するmail()関数はメールサーバーに接続し、サーバーと対話...

MySQL 5.7.17 zip インストールおよび設定チュートリアル MySQL 起動失敗の解決策

MySQL 5.7.17、現在最新バージョンのようです、ダウンロードアドレスここで、プラットフォーム...

docker を使用してシンプルな C/C++ プログラムをデプロイする方法

1. まずhello-world.cppファイルを作成しますプログラムコードは次のとおりです。 #i...

CentOS7で新しいデータディスクをマウントするための完全な手順

序文新しい VPS を購入しました。新しい VPS のデータ ディスクはデフォルトではシステムにマウ...

Linux で誤って削除したメッセージ ファイルを復元する方法

プロセスで使用されていて、誤って削除されたファイルがある場合、それらを回復することができます。プロセ...