有一个input框,每次输入都要触发一次change事件,其实这大可不必,比如我输入 “上海” 两个字,竟然触发了9次。
- <body>
- <input type="text" />
- <script src="./t.js"></script>
- </body>
- const input = document.querySelector('input')
- input.oninput = function() {
- console.log(this.value)
- }

假如每次change都会和后端发生一次交互,这个性能就会很惨。
怎么才能让这个次数变的少?
用户触发事件过于频繁,只要最后一次事件的操作。比如我们可以设置500ms,只要在500ms内你一直还在输入,也就是说你的停顿是少于500ms的,那么就不触发change事件里的复杂逻辑。在执行复杂逻辑之前就把定时器清理掉。
- const input = document.querySelector('input')
- let t = null
- input.oninput = function() {
- if (t !== null) {
- clearTimeout(t)
- }
- t = setTimeout(() => {
- // 用一句打印代替复杂的业务逻辑
- console.log(this.value)
- }, 500)
- }
上面的代码有2个大毛病:
用闭包来改进这段代码

上面,在调用debounce的时候,第一个参数是传递一个函数,
我们传的是一个() => {console.log(this.value)} ,这里的this是window,但是我们想要的是input。
所以,可以用call的方式来
- const input = document.querySelector('input')
- input.oninput = debounce(function() { // 这里如果用箭头函数,还是指向window,不能用箭头函数
- // 业务逻辑,用一个打印代替
- console.log(this.value)
- }, 500)
-
- function debounce(fn, delay) {
- let t = null
- return function() {
- if (t !== null) {
- clearTimeout(t)
- }
- t = setTimeout(() => {
- // 执行业务逻辑,这里的this就是input 事件对象
- console.log('this: ', this)
- fn.call(this)
- }, delay)
- }
- }

四、节流
有一种情形,滚动事件,会执行很多次。
- window.onscroll = function() {
- console.log('---------')
- }

你看,不到一秒钟随便滚动一下就是100多次。
防抖:只执行最后一次;
节流:控制执行次数;让耗性能的方法减少执行次数;
和防抖是一样的写法
- window.onscroll = throttle(() => {
- // 这里是业务逻辑,this:window
- console.log('..........')
- }, 500)
-
- function throttle(fn, delay) {
- let flag = true
- return function() {
- if (flag) {
- setTimeout(() => {
- fn.call(this)
- flag = true
- }, delay)
- }
- flag = false
- }
- }
