1. addEventListener与on的区别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>addEventListener与on</title>
</head>
<body>
<div style="height: 20000px"></div>
</body>
</html>
<script>
function say (num) {
return function () {
console.log(num)
}
}
window.addEventListener('scroll',say(1))
window.addEventListener('scroll',say(2))
window.onscroll= say(3)
window.onscroll = say(4)
function removeScroll () {
console.log('remove')
}
window.addEventListener('scroll',removeScroll)
window.removeEventListener('scroll',removeScroll)
</script>
- 当页面滚动的时候,控制台会打印出1,2,4。不会出现3。说明on触发事件只能注册一次。
- ele.addEventListener('eventType',fn,bol)中的第三个bol参数 true:表示事件为捕获阶段。默认为false,冒泡阶段
防抖和节流 (性能优化)
js中有许多事件都是频繁触发,例如scroll,resize,touchMove...这些事件如果对dom进行了操作,会造成很大的损耗,页面卡顿。怎么优化?可以通过对事件进行防抖和节流操作!
防抖
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>addEventListener与on</title>
</head>
<body>
<div style="height: 20000px"></div>
</body>
</html>
<script>
// 防抖动函数
function debounce(func, wait) {
let timeout = null
return function() {
let context = this, args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
func.apply(context, args);
}, wait);
};
};
let myEfficientFn = debounce(function(item) {
console.log(item.target)
}, 250);
// 绑定监听
window.addEventListener('scroll', myEfficientFn);
// setTimeout(() => {
// window.removeEventListener('scroll', myEfficientFn);
// }, 3000)
</script>
上述的大概意思就是当你滑动的时候,会在你停下鼠标后0.25s后才会触发你需要的回调函数,而不是每次滑动触发回调函数。
节流1
发抖确实可以解决部分需求,但是会有个问题,事件的回调函数,必须在滑动停下后,才执行。那么节流可以解决这个问题。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>addEventListener与on</title>
</head>
<body>
<div style="height: 20000px"></div>
</body>
</html>
<script>
// 简单的节流函数
function throttle(func, wait, mustRun) {
let timeout, startTime = new Date();
return function () {
let context = this, args = arguments, curTime = new Date();
clearTimeout(timeout);
if(curTime - startTime >= mustRun){
func.apply(context,args);
startTime = curTime;
}else{
timeout = setTimeout(function () {
func.apply(context, args);
}, wait);
}
};
};
// 实际想绑定在 scroll 事件上的 handler
function realFunc (event){
console.log(event);
}
let testFunc = throttle(realFunc,500,2000)
// 采用了节流函数
window.addEventListener('scroll',testFunc);
setTimeout(() => {
window.removeEventListener('scroll',testFunc)
},3000)
</script>
上述demo的意思是:每过2000ms会触发一次,当停止滑动500s后会触发一次
raf节流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>addEventListener与on</title>
</head>
<body>
<div style="height: 20000px"></div>
</body>
</html>
<script>
function rafThrottle(func){
return function () {
let ticking = false
let args = arguments, context = this
if(!ticking) {
requestAnimationFrame(function () {
func.apply(context, args);
ticking = false;
});
ticking = true;
}
}
}
// 实际想绑定在 scroll 事件上的 handler
function realFunc (event){
console.log(event);
}
const testFnc = rafThrottle(realFunc)
// 滚动事件监听
window.addEventListener('scroll', testFnc);
setTimeout(() => {
window.removeEventListener('scroll',testFnc)
},3000)
</script>