- A+
所属分类:Web前端
先上结论:
防抖 :只执行最后一次 (常用语输入框)
节流: 控制执行的次数 (常下拉滚动条时进行数据请求)
防抖代码: (这是未封装的,防抖代码和业务代码写在一起了)
<body> <input type="text" /> <script> // 防抖:用户触发事件过于频繁,只要最后一次事件的操作 let inp = document.querySelector('input') //定义全局变量 t let t = null inp.oninput = function () { if (t !== null) { clearTimeout(t) } t = setTimeout(() => { console.log(this.value) }, 500) } </script> </body>
这是封装后的,同时利用了闭包:
<body> <input type="text" /> <script> let inp = document.querySelector('input') inp.oninput=debounce(function(){ console.log(this.value); },500) // 封装防抖函数 //fn 为传入的业务逻辑 delay 为延迟时间 function debounce(fn,delay){ let t = null; return function () { if (t !== null) { clearTimeout(t) } t = setTimeout(() => { // 使用call 改变 this的指向 如果不更改的话,再上面调用的 this.value 中this 指向为window fn.call(this); }, delay) } } </script> </body
节流代码:(这是未封装的,防抖代码和业务代码写在一起了)
<style> body { height: 2000px; } </style> <script> // 节流 控制执行的次数 let flag =true window.onscroll=function(){ if(flag){ setTimeout(()=>{ console.log("hello world"); flag=true },500) } flag =false } </script>
和防抖类似,也进行了封装,代码如下:
<style> body { height: 2000px; } </style> <script> window.onscroll = throttle(function () { console.log('hello world') }, 500) function throttle(fn, delay) { let flag = true return function () { if (flag) { setTimeout(() => { flag = true // 使用call 改变 this的指向 fn.call(this) }, delay) } flag = false } } </script>
这里解释一下flag 的作用。按照执行顺序讲下吧,从上到下分别为(1 2 3):
(先执行的)第一个 let flag = true; 先定义flag,用来判断使用运行定时器。相信都看得懂,废话不多说。
(第二执行)第三个 调用定时器之后,需要将 flag 暂时定义为 flag 避免短时间再次触发定时器。
(第三个执行的) 第二个 先讲下,为啥第二个最后一个执行,这是因为 js 的同步与异步。 js会先执行同步任务,碰到异步任务 会加到 另外一个线程(只是这样解释,其实不是) 等待其运行结束后,再进行调用。要是不明白,可以先去百度搜索下,同步与异步 的概念。
这样的话,在定时器 运行结束后,flag 就被改为了 true 用来等待 下次激活使用。
如有解释不对的地方,还望指正。