web面试题
本人是一个web前端开发工程师,主要是vue框架,整理了一些面试题,今后也会一直更新,有好题目的同学欢迎评论区分享 ;-)
web面试题专栏:点击此处
场景分析
百度首页的输入框input,是不是随着你的输入而实时更新最新的下拉可选项,这个如果不做防抖,那是不是敲下一个键盘就需要发起一次请求。
防抖的原理
防抖就是单位时间内,如果只有一个操作,时间到了就执行;如果在单位时间内,你又操作了,那就需要重新计时,以保证最后一次操作是使用者本身已经确定完毕的。
就比如上方的input,延迟500毫秒为例子。
你如果500毫秒内,没有再次输入,那是不是意味着,可以向服务器发起请求了;但是但在100毫秒的时候,你又输了一个字符,那是不是意味着,你还没有确定,这个时候又重新开始计时
防抖的实现
这里只做部分代码的抽取,源码在最后面,可运行的HTML文件。
1. 不做防抖的例子
这里不做防抖,方便对比~
// dom
<input id="input1" type="text" />
// js
let input1 = document.getElementById("input1");
input1.addEventListener("input", function (e) {
// 不能使用箭头函数,避免作用域提升
console.log("第一个不做防抖的输入框:", this.value);
});
2. 全局timer做防抖的例子
这里用setTimeout来判断是否达到运行时间了,但是用了全局timer来标识。
思考1:如果有多个需求要防抖处理,是不是有好多个timerx变量?要怎么封装才好呢?
思考2:另外,业务跟功能夹杂在一起了,能不能抽取出防抖这个功能呢?
注意:打印事件对象e!!! 闭包不能直接获取到~
// dom
<input id="input2" type="text" />
// js
let input2 = document.getElementById("input2");
let timer = null;
input2.addEventListener("input", function (e) {
// 如果已经有事件了,则清空计时器重新执行新的,保证是最新一次执行
if (timer != null) {
clearTimeout(timer);
}
// 这里需要箭头函数,这样就可以提升到input2这个作用域
timer = setTimeout(() => {
console.log(e);
console.log("全局timer制作的防抖:", this.value);
}, 1000);
});
3. 闭包做防抖的例子
这个东西比较难理解,不懂的同学可以先看看闭包~
注意1:this的作用域问题,需要用call来处理
注意2:事件e要怎么在闭包中传递
// dom
<input id="input3" type="text" />
// js
let input3 = document.getElementById("input3");
input3.addEventListener(
"input",
// 这边新建了一个闭包,返回的是一个函数,保存了改作用域的变量timer
// 这里的e,不是通过addEventListener调用传入的,是addEventListener调用了闭包,往闭包里面传参了
// 闭包再通过call传递参数
debounce(function (e) {
console.log("e:", e);
console.log("闭包做的防抖 input3:", this.value);
}, 1000)
);
/**
* @author: Penk
* @description: 防抖,通过闭包保存timer变量
* @param {*} fn
* @param {*} timeout
* @return {*}
*/
function debounce(fn, timeout) {
let timer = null;
return function (e) {
// 如果已经有事件了,则清空计时器重新执行新的,保证是最新一次执行
if (timer != null) {
clearTimeout(timer);
}
// 这里需要箭头函数,这样就可以提升到input2这个作用域
timer = setTimeout(() => {
fn.call(this);
}, timeout);
};
}
源码
<!--
* @Author: Penk
* @LastEditors: Penk
* @LastEditTime: 2022-11-11 20:15:52
* @FilePath: \web面试题\防抖.html
* @email: 492934056@qq.com
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>js防抖</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
padding: 20px;
}
.debounceWarper .debounceItem {
display: flex;
margin-top: 20px;
}
.debounceWarper .debounceItem .debounceItem_label {
width: 230px;
}
.tooltips {
display: block;
color: red;
font-size: 12px;
margin-top: 2px;
}
</style>
</head>
<body>
防抖:防抖就是在单位时间内只执行最后一次操作
<!-- 防抖:控制高频事件 -->
<div class="debounceWarper">
<div class="debounceItem">
<span class="debounceItem_label">不做防抖的输入框:</span>
<input class="debounceItem_value" id="input1" type="text" />
</div>
<div class="debounceItem">
<span class="debounceItem_label">全局timer做防抖的输入框:</span>
<input class="debounceItem_value" id="input2" type="text" />
</div>
<span class="tooltips"
>这里用setTimeout来判断是否达到运行时间了,但是用了全局timer来标识。</span
>
<span class="tooltips"
>思考:1.如果有多个该怎么样,要怎么封装才好呢?</span
>
<span class="tooltips"
>
2.另外,业务跟功能夹杂在一起了,能不能抽取出防抖这个功能呢?</span
>
<div class="debounceItem">
<span class="debounceItem_label">闭包做防抖的输入框:</span>
<input class="debounceItem_value" id="input3" type="text" />
</div>
<div class="debounceItem">
<span class="debounceItem_label">闭包做防抖的输入框:</span>
<input class="debounceItem_value" id="input4" type="text" />
</div>
</div>
<script>
// -----------------------不做防抖的输入框:---------------------- //
let input1 = document.getElementById("input1");
input1.addEventListener("input", function (e) {
// 不能使用箭头函数,避免作用域提升
console.log("第一个不做防抖的输入框:", this.value);
});
// -----------------------全局timer做防抖的输入框:---------------------- //
let input2 = document.getElementById("input2");
let timer = null;
input2.addEventListener("input", function (e) {
// 如果已经有事件了,则清空计时器重新执行新的,保证是最新一次执行
if (timer != null) {
clearTimeout(timer);
}
// 这里需要箭头函数,这样就可以提升到input2这个作用域
timer = setTimeout(() => {
console.log("e:", e);
console.log("全局timer制作的防抖:", this.value);
}, 1000);
});
// -----------------------闭包做防抖的输入框:---------------------- //
let input3 = document.getElementById("input3");
input3.addEventListener(
"input",
// 这边新建了一个闭包
debounce(function (e) {
console.log("e:", e);
console.log("闭包做的防抖 input3:", this.value);
}, 1000)
);
let input4 = document.getElementById("input4");
input4.addEventListener(
"input",
// 这边新建了另外一个闭包
debounce(function (e) {
// console.log("e:", e);
console.log("闭包做的防抖 input4:", this, this.value);
}, 1000)
);
/**
* @author: Penk
* @description: 防抖,通过闭包保存timer变量
* @param {*} fn
* @param {*} timeout
* @return {*}
*/
function debounce(fn, timeout) {
let timer = null;
return function (e) {
// 如果已经有事件了,则清空计时器重新执行新的,保证是最新一次执行
if (timer != null) {
clearTimeout(timer);
}
// 这里需要箭头函数,这样就可以提升到input2这个作用域
timer = setTimeout(() => {
fn.call(this,e);
}, timeout);
};
}
</script>
</body>
</html>
源码页面展示图
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/66362.html