前言
本文将重点介绍前端性能优化方法之一的防抖和节流。首先解释了它们的概念和原理,然后探讨了它们在前端开发中的应用场景,如输入框搜索、滚动事件等。最后,通过简单的代码示例展示了如何实现防抖和节流函数。通过学习和应用这两种技术,我们可以有效地减少不必要的函数执行次数,提高页面响应速度,从而改善用户体验。
什么是防抖?
定义:延迟一段时间再触发,如果再延迟时间内又触发,则清除上一个定时,再开始新的定时。
应用场景:搜索框联想、屏幕伸缩。
什么是节流?
定义:在一段时间间隔内,稀释事件的触发频率,不论事件被触发几次,只执行一次。
应用场景:
单位时间内,鼠标不论点击多少次,只执行一次(搜索内容未变化时)。
在使用列表下拉滚动加载时,用于定时监听滚动事件。
应用实例
防抖实例
下面是用防抖实现一个简易版搜索框联想+防抖
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<header>
<h1>防抖解决搜索联想词</h1>
</header>
<main>
<input type="text" id="search-input" placeholder="Search...">
<ul id="suggestions-list"></ul>
</main>
<script>
// 1.防抖函数
function debounce(func, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
// 2.定义两个变量分别存储输入框id和联想词id
const searchInput = document.getElementById('search-input');
const suggestionsList = document.getElementById('suggestions-list');
// 3.模拟异步请求获取联想词
function fetchSuggestions(keyword) {
const suggestions = ['apple', 'banana', 'cherry', 'date', 'elderberry', 'fig'];
renderSuggestions(suggestions.filter(suggestion =>
suggestion.toLowerCase().startsWith(keyword.toLowerCase())
));
}
// 4.联想词显示函数
function renderSuggestions(suggestions) {
suggestionsList.innerHTML = '';
suggestions.forEach((suggestion) => {
const listItem = document.createElement('li');
listItem.textContent = suggestion;
suggestionsList.appendChild(listItem);
});
}
// 定义默认方法,调用闭包方法,设置定时时间和防抖结束后调用的函数
const debounceFetchSuggestions = debounce(fetchSuggestions, 1000);
// 给输入框id增加监听器
searchInput.addEventListener('input', function () {
// 获取去空格value值
const keyword = searchInput.value.trim();
// 调用闭包方法
debounceFetchSuggestions(keyword);
});
</script>
</body>
</html>
讲解代码
1.在html代码中写input、ul,一个用来输入,一个用来返回联想词,并给它们设置id值用于添加监听以及更新内容。
2.定义防抖函数:debounce
外层两个参数分别存储防抖事件处理方法以及延迟毫秒数。
timer用于存储定时器的引用。内部返回的闭包函数如果在延迟时间内再次被调用,则timer重置,且重新开始计时。
如果延迟时间内没有再次被调用,则调用func也就是fetchSuggestions函数,这里用到了一个方法apply,该方法有两个参数,第一个参数决定this指向的是哪个上下文环境,这里指向的是当前上下文环境,第二个为普通参数。
3.定义两个变量searchInput、suggestionsList分别把input和ul的id进行赋值。
4.模仿异步接口写方法,该方法第一层是定义了所有联想词,第二层是调用联想词显示函数。这里用到filter过滤和筛选,这里就不赘述了。
5.联想词显示函数,这里用到的是forEach遍历,createElement创建HTML元素,以及用li和appendchild加元素。
6.定义默认方法,并且设置事件处理方法和延迟毫秒数。
7.给输入框加监听器监听器中使用trim去除空格,且调用闭包函数。
节流实例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<header>
<h1>节流解决搜索联想词</h1>
</header>
<main>
<input type="text" id="searchInput">
</main>
<script>
const searchInput = document.getElementById('searchInput');
function search(query) {
// 模拟搜索操作,这里可以替换为实际的搜索逻辑
console.log(`搜索: ${query}`);
}
// 使用节流函数处理搜索输入
const throttleSearch = throttle(search, 1000); // 设定延迟为500毫秒
searchInput.addEventListener('keyup', function(event) {
const query = event.target.value.trim();
throttleSearch(query);
});
// 节流函数实现
function throttle(func, delay) {
let timerId;
let lastExecuted = 0;
return function(...args) {
const now = Date.now();
const timeSinceLastExecution = now - lastExecuted;
if (timeSinceLastExecution >= delay) {
func.apply(this, args);
lastExecuted = now;
} else {
clearTimeout(timerId);
timerId = setTimeout(() => {
func.apply(this, args);
lastExecuted = Date.now();
}, delay - timeSinceLastExecution);
}
};
}
</script>
</body>
</html>
我们首先获取了搜索框的元素,并定义了一个 search 函数用于模拟搜索操作。然后,我们使用节流函数 throttle 对搜索函数进行包装,设定了一个1000毫秒的延迟。
接下来,监听搜索框的 keyup 事件,并获取用户输入的查询词。每次键盘释放时,会调用节流函数 throttleSearch,并将查询词作为参数传递给搜索函数 search。
在节流函数的实现中,记录了最后一次函数执行的时间戳,并根据设定的延迟来判断是否立即执行函数或设置定时器延迟执行函数。
当用户在搜索框中输入内容时,搜索请求会在一定的时间间隔内被触发,避免了频繁的搜索请求。