闭包、防抖、节流、input搜索、窗口计算、图片懒加载
-
防抖debounce
-
当持续触发事件,一定时间内没有再触发事件,事件处理函数才会执行一次;如果设定的时间到来之前,又一次触发了事件,就重新开始延时
-
input输入搜索
// timer变量需要一直保存在内存当中,内存的泄露,用闭包来实现 function debounce(delay) { let timer return function(value) { clearTimeout(timer) timer = setTimeout(() => { console.log(value) }, delay) } } // 如果这里不这样写,而是在keyup的callback中调用debouce()()就没有意义了 // 定义无数timer var debounceFunc = debounce(1000) input.addEventListener('keyup', function(e) { debounceFunc(e.target.value) }) // react中 handleChangeCallback = (args) => { const value = args[0] if (value.trim() === '') { console.log(value) } else { console.log(value) } } debounceFunc = debounce(this.handleChangeCallback, 500) handleChange = (e) => { this.debounceFunc(e.currentTarget.value) } <Input onChange={this.handleChange} />
function debounce(delay, fn) { let timer return function() { // 箭头函数没有argument var args = arguments clearTimeout(timer) timer = setTimeout(() => { fn(args) }, delay) } }// 有返回值 function debounce(func, wait) { var timeout, result; return function () { var args = arguments; clearTimeout(timeout) timeout = setTimeout(() => { result = func(args) }, wait); return result } } -
-
节流throttle
-
一段时间内只做一件事情
-
例子
const button = document.getElementById('button') function thottle(delay, fun) { let timer return function () { let args = arguments if (!timer) { timer = setTimeout(() => { fun(args) // timer如果不赋值为null不会因为执行完而自动变为null的 timer = null }, delay) } } } handleClick = () => { console.log(111) } let thottleFun = thottle(1000, handleClick) button.addEventListener('click', () => { thottleFun() }) // 如果下面这种写法可以直接调用thottle // button.onclick = thottle(1000, handleClick) // 这样写也可以,因为相当于回调函数直接是debounce函数 // button.addEventListener('click', debounce(1000, handleClick)) // addEventListener监听某个事件,只要发生这个事件就会执行回调函数 // 这个回调函数本身,不会执行多次 -
图片懒加载
var img = document.getElementsByTagName('img') var num = img.length var n = 0 // 存储图片加载到的位置,避免每次都从第一张图片开始便利 var _clientHeight = document.documentElement.clientHeight // 可见去遇高度 var _scrollTop = document.documentElement.scollTop || document.body.scrollTop // 滚动条距顶部高度 // 监听窗口变化重新计算可视区域 function computedClientHeight() { _clientHeight = document.documentElement.clientHeight // 可见区域高度 } // 页面载入完毕加载可视区域内的图片 lazyload() function lazyload() { // 获取滚动条距离顶部高度 _scrollTop = document.documentElement.scrollTop || document.body.scrollTop for (var i = n; i < num; i++) { console.log(img[i].offsetTop) if (img[i].offsetTop < _scrollTop + _clientHeight) { if (img[i].getAttribute('src') === '') { img[i].src = img[i].getAttribute('data-src') } n = i + 1 } } } // 使用节流函数实现性能较好的懒加载 window.addEventListener('scroll', throttle(lazyload, 100)) // 使用防抖函数优化不断出发的窗口变化 window.addEventListener('resize', debounce(800, computedClientHeight)) function debounce(delay, fn) { let timer return function () { // 箭头函数没有arguments var args = arguments clearTimeout(timer) timer = setTimeout(() => { fn(args) }, delay) } } function throttle(fn, delay) { let timer return function () { if (!timer) { timer = setTimeout(() => { fn() timer = null }, 1000) } } }
function throttle(fn, delay) { let timer return function() { if (!timer) { timer = setTimeout(() => { fn() timer = null }, 1000) } } } -