序文一般的なビジネス シナリオでは、検索ボックスへの入力が完了した後、検索データを取得するために関連リクエストを送信する必要があります。頻繁にイベントがトリガーされると、インターフェース要求が頻繁に発生しすぎます。したがって、リソースの無駄を避けるために、不必要なリクエストを禁止するようにこれを制限する必要があります〜 ビジネスシナリオを例に挙げましょうコンセプト:手ぶれ補正機能の紹介 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); } 要点:
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 を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: Centos 7 sshd の変更 | ルートログインの禁止と sshd ポートスクリプトの定義
>>: MySQL データのバックアップと復元のサンプル コード
随分前に「Patterns for Sign Up & Ramp Up」を読み終えました。今...
1. 物件リストコードをコピーコードは次のとおりです。色: #999999 テキスト色フォントファミ...
Vue エコシステムには Vite と呼ばれる新しいビルド ツールがあり、Vue CLI よりも 1...
目次前面に書かれた1. Ngixnイメージの作成2. Java Web (Tomcat) アプリケー...
最近、私は「ぶどうコレクション」というプロジェクトに取り組んでいます。簡単に言うと、Budou ペー...
3つの仮想マシン132、133、134を群がらせる1. クラスターを初期化し、自分自身をクラスターに...
LinuxでのMySQL5.7 rpmのインストール方法を参考までに記録します。具体的な内容は以下の...
必要なときにサービスを有効にし、必要がないときは無効にします。データベース サービスを管理する方法:...
データベースのパフォーマンスに関する話面接では、「データベースにどのくらい精通していますか?」など、...
データの初期化 `test_01` が存在する場合はテーブルを削除します。 テーブル「test_01...
この記事は主に、以前のインストール方法を使用して MySQL 5.7.14 をインストールするときに...
目次1. 主な機能2. 実装のアイデア3. コードの実装4. エフェクト表示V. 結論1. 主な機能...
目次1. Tomcatを監視する方法2. Java独自の監視コマンド3. Tomcatのトラブルシュ...
これまで使用していたイメージはすべて DockerHub パブリック リポジトリから取得していました...
1. イベント委任とは何ですか?イベント委譲: イベントバブリングの特性を利用して、子要素に登録すべ...