一部のブラウザ イベント (ウィンドウのサイズ変更やページのスクロールなど) は、短期間に複数回迅速にトリガーされることがあります。たとえば、ページ ウィンドウのスクロール イベントをリッスンし、ユーザーがページをすばやく下にスクロールし続けると、スクロール イベントが 3 秒間に数千回発生し、重大なパフォーマンスの問題が発生する可能性があります。
面接中にアプリケーションの構築について話し合ったときに、スクロール、ウィンドウのサイズ変更、キーの押下などのイベントが発生した場合は、ページの速度とパフォーマンスを向上させるためのデバウンスと機能スロットルについて必ず言及してください。この二人の兄弟の本質は、クロージャという形で存在します。イベントに対応するコールバック関数をラップし、時間情報を自由変数の形式でキャッシュし、最後に setTimeout を使用してイベントのトリガー頻度を制御します。
スロットル: 最初の人が最終決定権を持ちます
スロットルの中心的な考え方は次のとおりです: 一定期間内はノートリガーの数に関係なく、各コールバックについて、初回のみを認識し、タイマーが期限切れになったときに応答します。
最初にちょっとした話をさせてください。ある乗客が飛行機から降りたばかりで車が必要になったので、空港にある唯一の空港バスに電話して迎えに来ました。運転手は、もう来てしまったから、もう少し人を乗せて一緒に行くべきだと思いながら、空港まで車を走らせました。そうすれば、旅の価値があるでしょう。10 分待って様子を見てみましょう。そこで運転手はタイマーをオンにし、後ろの客に次々とバスに乗車するよう挨拶した。この10分間は、後ろから降りた乗客のみがこのバスに乗れ、10分経過すると、どんなに後ろの乗客がバスに混んでいなくても、このバスは追い送られなければなりません。
このストーリーでは、「ドライバー」は出発のタイミングを制御するスロットルであり、「乗客」は頻繁な運行イベントによって流入し続けるコールバック タスクであり、それを受け入れる必要があります。 「運転士」の手配、「タイマー」は、「運転士」が列車の発車を判断する根拠となる上記の自由変数形式の時刻情報、そして最後に「発車」という動作です。コールバック関数の実行に相当します。
要約すると、いわゆる「スロットリング」は、後続のコールバック要求を一定期間無視することによって実現されます。ゲストが配車を要求している限り、運転手はその人の代わりにタイマーを開始し、一定時間内に配車が必要な後続のゲストはすべてこの配車に乗るために列に並ぶ必要があり、誰も配車を呼び出すことはできません。もっと乗り物を。
これは実際のインタラクションに対応します。ユーザーがスクロール イベントをトリガーするたびに、このトリガー操作のタイマーが開始されます。一定期間、後続のすべてのスクロール イベントは「車の乗客」として扱われ、新しいスクロール コールバックをトリガーすることはできません。 「一定の期間」に達するまで、最初にトリガーされたスクロール イベントに対応するコールバックが実行され、「一定の期間内」にトリガーされた後続のスクロール コールバックはスロットル バルブによって無視されます。
今、一緒にスロットルを実現しましょう:
// fn是我们需要包装的事件回调, interval是时间间隔的阈值 function throttle(fn, interval) { // last为上一次触发回调的时间 let last = 0 // 将throttle处理结果当作函数返回 return function () { // 保留调用时的this上下文 let context = this // 保留调用时传入的参数 let args = arguments // 记录本次触发回调的时间 let now = +new Date() // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值 if (now - last >= interval) { // 如果时间间隔大于我们设定的时间间隔阈值,则执行回调 last = now; fn.apply(context, args); } } } // 用throttle来包装scroll的回调 const better_scroll = throttle(() => console.log('触发了滚动事件'), 1000)
デバウンス: 最後の人が最終決定権を持っています
中心的なアイデア手ブレ防止優:最後までお待ちしております。一定期間内に、どれだけ多くのコールバックをトリガーしても、認識できるのは最後のコールバックだけです。
ドライバーの運転の話を続けます。今度は運転手はもっと忍耐強くなった。最初の乗客がバスに乗車した後、運転手は計時を開始します (たとえば 10 分)。 10 分以内に別の乗客が来た場合、運転手はタイマーをクリアし、さらに 10 分間待機し始めます (遅延待機)。そのような乗客が現れ、バスに乗ってから 10 分間新たな乗客が乗車しなくなるまで、運転手はこのバスには誰も乗る必要がないと判断し、そのまま走り去ってしまうでしょう。
デバウンスを理解するためにスロットルを比較してみましょう: スロットルのロジックでは、「最初の人が最終決定権を持っている」ため、最初の乗客の時間を計測するだけで、時間が経過するとコールバックが実行されます。デバウンスは「最後の人が最終決定権を持っている」と信じており、デバウンスは新しい乗客ごとに新しいタイマーを設定します。
デバウンスを一緒に実装します:
// fn是我们需要包装的事件回调, delay是每次推迟执行的等待时间 function debounce(fn, delay) { // 定时器 let timer = null // 将debounce处理结果当作函数返回 return function () { // 保留调用时的this上下文 let context = this // 保留调用时传入的参数 let args = arguments // 每次事件被触发时,都去清除之前的旧定时器 if(timer) { clearTimeout(timer) } // 设立新定时器 timer = setTimeout(function () { fn.apply(context, args) }, delay) } } // 用debounce来包装scroll的回调 const better_scroll = debounce(() => console.log('触发了滚动事件'), 1000)
スロットルを使用してデバウンスを最適化する
デバウンスの問題は、次のとおりです。 「複雑すぎる」我慢してください。想像してみてください。ユーザーが非常に頻繁に操作を行う場合、ユーザーは次の操作を実行する前にデバウンスで設定された遅延時間が終了するのを待たないため、デバウンスがユーザーのタイマーを再生成するたびに、コールバック関数は数え切れないほど遅延します。遅延が頻繁に発生すると、ユーザーからの応答が得られなくなり、ユーザーは「このページは行き詰まっている」という印象を与えてしまいます。
自己破滅を避けるために、スロットルのアイデアを借りて「最終的な」デバウンスを作成する必要があります。待っていただいても構いませんが、私には私の原則があります。遅延時間内であれば、サーバーのタイミングを再生成しますが、遅延時間が経過したらすぐにユーザーに応答する必要があります。スロットルとデバウンスのこの「組み合わせ」のアイデアは、多くの成熟したフロントエンド ライブラリによって、拡張されたスロットル関数の実装に適用されています。
// fn是我们需要包装的事件回调, delay是时间间隔的阈值 function throttle(fn, delay) { // last为上一次触发回调的时间, timer是定时器 let last = 0, timer = null // 将throttle处理结果当作函数返回 return function () { // 保留调用时的this上下文 let context = this // 保留调用时传入的参数 let args = arguments // 记录本次触发回调的时间 let now = +new Date() // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值 if (now - last < delay) { // 如果时间间隔小于我们设定的时间间隔阈值,则为本次触发操作设立一个新的定时器 clearTimeout(timer) timer = setTimeout(function () { last = now fn.apply(context, args) }, delay) } else { // 如果时间间隔超出了我们设定的时间间隔阈值,那就不等了,无论如何要反馈给用户一次响应 last = now fn.apply(context, args) } } } // 用新的throttle包装scroll的回调 const better_scroll = throttle(() => console.log('触发了滚动事件'), 1000) document.addEventListener('scroll', better_scroll)
lodash でデバウンスとデバウンスを使用します。 Vue のスロットリング
事件节流和防抖是提高性能或降低网络开销的好方法。虽然 Vue 1曾经支持对事件的节流和防抖,但是在Vue 2中为了保持核心的简单性,删除对事件的节流和防抖的支持。因此,在Vue 2对对事件进行防抖和节流我们可以使用 lodash
来做。
安装
可以通过 yarn 或 npm 安装 lodash。
# Yarn $ yarn add lodash # NPM $ npm install lodash --save
注意:如果我们不想导入lodash
的所有内容,而只导入所需的部分,则可以通过一些Webpack构建自定义来解决问题。 还可以使用lodash.throttle
和lodash.debounce
等软件包分别安装和导入lodash
的各个部分。
throttling 方法
要对事件进行节流处理方法非常简单,只需将要调用的函数包装在lodash的_.throttle
函数中即可。
<template> <button @click="throttledMethod()">Click me as fast as you can!</button> </template> <script> import _ from 'lodash' export default { methods: { throttledMethod: _.throttle(() => { console.log('I get fired every two seconds!') }, 2000) } } </script>
debouncing 方法
尽管节流在某些情况下很有用,但一般情况我们经常使用的是防抖。 防抖实质上将我们的事件分组在一起,并防止它们被频繁触发。 要在Vue组件中使用节流,只需将要调用的函数包装在lodash的_.debounce
函数中。
<template> <button @click="throttledMethod()">Click me as fast as you can!</button> </template> <script> import _ from 'lodash' export default { methods: { throttledMethod: _.debounce(() => { console.log('I only get fired once every two seconds, max!') }, 2000) } } </script>
参考:
相关推荐:
更多编程相关知识,请访问:编程入门!!
以上がVue で手ぶれ補正とイベントの調整を行うにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。