一、节流的概念和使用库实现节流
1.1. 认识节流
- 节流:当事件第一次被触发时,就会执行相应的回调函数。但是如果这个事件被频繁的触发的话,相应的函数并不会被频繁的执行,而是会以固定的频率执行。不管在这个频率之内触发多少次事件,函数的执行频率都是固定的
1.2. underscore实现节流
- underscore中实现了throttle(节流)方法,调用这个方法,将想要绑定在事件上的回调函数作为参数传入throttle方法即可
_.throttle(fn, time)
讯享网
讯享网<input type="text"> <!-- 通过CDN引入文件 --> <script src="https://cdn.jsdelivr.net/npm/underscore@1.13.6/underscore-umd-min.js"></script> <script> const inputEl = document.querySelector("input") let count = 0 inputEl.oninput = _.throttle(function() {
console.log("发送网络请求", count++, this.value) },5000) </script>
二、手写节流实现
2.1. 基本实现
<body> <input type="text"> <script> // 1.基本实现 function zdThrottle(fn, intervalTime) {
let startTime = 0 function _throttle() {
const nowTime = new Date().getTime() const waitTime = intervalTime - (nowTime - startTime) if (waitTime <= 0) {
fn() startTime = nowTime } } return _throttle } </script> <script> const inputEl = document.querySelector("input") let count = 0 inputEl.oninput = zdThrottle(function() {
console.log(`发送网络请求${
count++}`, this.value) }, 2000) </script> </body>
2.2. this和参数的绑定、取消立即执行
讯享网<body> <input type="text"> <script> // 2.this和参数的绑定、取消立即执行 function zdThrottle(fn, intervalTime, leading = true) {
let startTime = 0 function _throttle(...args) {
const nowTime = new Date().getTime() // 想要取消立即执行,就让第一次事件触发调用函数时的waitTime大于0即可 if (!leading && startTime === 0) {
startTime = nowTime } const waitTime = intervalTime - (nowTime - startTime) if (waitTime <= 0) {
fn.apply(this, args) startTime = nowTime } } return _throttle } </script> <script> const inputEl = document.querySelector("input") let count = 0 inputEl.oninput = zdThrottle(function(event) {
console.log(`发送网络请求${
count++}`, this.value, event) }, 2000, false) </script> </body>
2.3. 开启尾部执行:最后就算在规定的时间,事件没有触发,也照常执行一次回调函数
<body> <input type="text"> <script> // 3.开启尾部执行 function zdThrottle(fn, intervalTime, {
leading = true, trailing = false } = {
}) {
let startTime = 0 let timer = null function _throttle(...args) {
const nowTime = new Date().getTime() if (!leading && startTime === 0) {
startTime = nowTime } const waitTime = intervalTime - (nowTime - startTime) if (waitTime <= 0) {
if (timer) clearTimeout(timer) fn.apply(this, args) startTime = nowTime timer = null } if (trailing && !timer) {
timer = setTimeout(() => {
fn.apply(this, args) // 一定要将现在的时间重新通过new Date()获得再赋给开始时间 // 不能拿上面的nowTime的原因是因为...用文字有点难表达,但是跟事件循坏和事件队列中的任务执行时机是有 关的,自己多想一下即可 startTime = new Date().getTime() timer = null }, waitTime) } } return _throttle } </script> <script> const inputEl = document.querySelector("input") let count = 0 inputEl.oninput = zdThrottle(function(event) {
console.log(`发送网络请求${
count++}`, this.value, event) }, 2000, {
leading: false, trailing: true }) </script> </body>
2.4. 取消最后一次执行的功能
讯享网<body> <input type="text"> <button class="cancel">取消</button> <script> // 4.添加取消执行的功能 function zdThrottle(fn, intervalTime, {
leading = true, trailing = false } = {
}) {
let startTime = 0 let timer = null function _throttle(...args) {
const nowTime = new Date().getTime() if (!leading && startTime === 0) {
startTime = nowTime } const waitTime = intervalTime - (nowTime - startTime) if (waitTime <= 0) {
if (timer) clearTimeout(timer) fn.apply(this, args) startTime = nowTime timer = null } if (trailing && !timer) {
timer = setTimeout(() => {
fn.apply(this, args) startTime = new Date().getTime() timer = null }, intervalTime) } } // 一个函数也是对象,所以是可以给添加一个方法的 _throttle.cancel = function() {
clearTimeout(timer) } return _throttle } </script> <script> const inputEl = document.querySelector("input") const cancelEl = document.querySelector(".cancel") let count = 0 // 这个返回的函数(对象)里面有cancel方法,直接调用即可取消最后一次的函数执行 const returnValue = zdThrottle(function(event) {
console.log(`发送网络请求${
count++}`, this.value, event) }, 2000, {
trailing: true }) inputEl.oninput = returnValue cancelEl.onclick = function() {
returnValue.cancel() } </script> </body>
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/45218.html