序文一般的なビジネス シナリオでは、検索ボックスへの入力が完了した後、検索データを取得するために関連リクエストを送信する必要があります。頻繁にイベントがトリガーされると、インターフェース要求が頻繁に発生しすぎます。したがって、リソースの無駄を避けるために、不必要なリクエストを禁止するようにこれを制限する必要があります〜 ビジネスシナリオを例に挙げましょうコンセプト:手ぶれ補正機能の紹介 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 データのバックアップと復元のサンプル コード
目次1 システムの紹介2 システムショートカット3 一般的なシステムコマンド1 システムの紹介 1....
1. なぜパッケージングを行うのですか?全体的なコード呼び出し、リクエストの公開処理、パーソナライズ...
これ以上無駄話をして時間を無駄にしないので、今日の話題を始めましょう。 HTML のメタタグ1. メ...
1. 最初の方法は、ローカルのTomcatを起動してJSPを表示することです。 tomcatのweb...
概要インデックス作成は、MySQL で習得しなければならないスキルであり、MySQL クエリの効率を...
本日の投稿では、Web デザインで使用される円形要素の優れた例をいくつか挙げ、美しい丸いボタン、メニ...
目次序文webpack-deb サーバーwebpack-dev-server 起動エラー解決策1解決...
<br />しばらくの間、多くの人が XHTML の使い方を知らないことに気付きました。...
最近はビッグデータで遊んでいます。友人が私のところに来て、オンラインの Tomcat が不可解に終了...
Angular Cookie の読み取りおよび書き込み操作のコードは次のようになります。 var a...
バックエンド管理プロジェクトを開発する場合、バックエンドのユーザーデータをカウントし、折れ線グラフや...
1 公式ウェブサイトから MySQL 5.6 バージョンの圧縮パッケージmysql-5.6.36-w...
目次1. MySQL で現在の時刻を表現するにはどうすればよいでしょうか? 2. TIMESTAMP...
この記事は主にPostgreSQLマテリアライズドビューのプロセス分析について紹介します。サンプルコ...
HTML 開発の歴史: HTML は英語で Hypertext Marked Language の...