序文一般的なビジネス シナリオでは、検索ボックスへの入力が完了した後、検索データを取得するために関連リクエストを送信する必要があります。頻繁にイベントがトリガーされると、インターフェース要求が頻繁に発生しすぎます。したがって、リソースの無駄を避けるために、不必要なリクエストを禁止するようにこれを制限する必要があります〜 ビジネスシナリオを例に挙げましょうコンセプト:手ぶれ補正機能の紹介 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 データのバックアップと復元のサンプル コード
以下のコードをDreamweaverのコードエリアにコピーすると、プレビュー時に以下の画像が表示され...
この記事では、実際に発生した問題をもとに、git の設定に関する内容を紹介します。コマンド: git...
Ubuntu が今日のデスクトップ ユーザーの間で最も人気のある Linux オペレーティング シス...
目次ウェブ開発1. Web開発の概要Tomcatのインストールと設定Tomcatをインストールする2...
目次1. タスクキュー2. 混乱を招く問題を説明する1. setTimeout(f1,0)とは何です...
この記事の例では、テーブルを動的に生成するjsの具体的なコードを参考までに共有しています。具体的な内...
以前、raspbian で実行したときに opencv の一部の依存関係をパッケージ化できず、一部の...
本日は、Web 開発で使われる基本的な概念と技術を初心者向けに紹介します。A から Z まで合計 2...
目次JavaScript のプライベート クラス フィールドとプライバシーの必要性JavaScrip...
a および href 属性 HTML では、英語ではアンカーと呼ばれるハイパーリンクを表すために &...
PHPのメール関数を使用してメールを送信するmail()関数はメールサーバーに接続し、サーバーと対話...
MySQL 5.7.17、現在最新バージョンのようです、ダウンロードアドレスここで、プラットフォーム...
1. まずhello-world.cppファイルを作成しますプログラムコードは次のとおりです。 #i...
序文新しい VPS を購入しました。新しい VPS のデータ ディスクはデフォルトではシステムにマウ...
プロセスで使用されていて、誤って削除されたファイルがある場合、それらを回復することができます。プロセ...