网页性能优化03-函数防抖

2024-09-02 15:48

本文主要是介绍网页性能优化03-函数防抖,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.1-函数防抖

1.函数防抖介绍

  • 1.什么是函数防抖? (debounce)

    • 网上主流解释:函数防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
      • 参考博客:https://www.jianshu.com/p/f9f6b637fd6c
      • 参考博客:https://segmentfault.com/a/1190000018445196
    • 笔者解释
      • 先理解什么是抖动?:例如用户鼠标轻微晃动,快速划过某一个元素(用户本身不想触发,只是鼠标误触发,常见于鼠标事件 移入/移出/移动 )。 例如输入框手机和邮箱验证,用户在不停的输入,还没有输完的时候其实是不需要验证的,应该等用户输入完毕后再验证。
      • 防抖 :如果用户鼠标轻微晃动,在某一个元素上停留时间很短,则认为是用户误触发,则不执行本次事件处理函数
        • 一句话总结:用户连续多次触发某个事件,则只执行最后一次
      • 由于函数防抖 属于 前端中的 网页性能优化技术,因此初学者刚开始学习会有一些吃力,并且很多网站都没有做防抖处理(性能优化)
        • 没有函数防抖的真实案例:http://www.elong.com/?semid=ppzqbaidu
          • 这是一个旅游类网站,上面酒店类型选择没有做防抖处理,用户体验很差
        • 有函数防抖的真实案例:https://xyq.163.com/
          • 这是网易梦幻西游官网,在网页底部选择职业的手风琴位置有做防抖处理,用户体验较好
  • 没有做函数防抖处理的用户体验如下

    • 假设当前鼠标在第一张,此时用户想看第五张。正常情况下,鼠标会依次触发 第二、第三、第四张的移入事件,但这不是用户真正想要触发的(误触发)

在这里插入图片描述

  • 有做函数防抖处理的用户体验如下
    • 用户从第一张 滑动到第五张,由于鼠标在 第二、第三、第四张停留时间很短(假设小于0.5秒),所以判定为用户误触发,则不触发对应的事件处理函数

在这里插入图片描述

2.函数防抖解决思路

  • 使用定时器:保证用户多次触发事件时,以最后一次触发为准

  • 1.每一次移入元素时 : 不立即触发该事件处理函数,而是开启定时器,间隔0.5s(防抖间隔)之后再执行事件处理函数。

    • 此时并没有彻底解决函数防抖,因为用户多次触发事件时,每一个定时器都会在0.5s之后,依次执行
  • 2.每一次移入元素时 : 先清除上一次的定时器

    • 保证用户多次触发事件时,以最后一次触发为准
  • 注意点:定时器中的this默认为window,需要使用上下文模式bind()动态修改为当前事件源

在这里插入图片描述

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>动画-案例《手风琴》</title><style>* {margin: 0;padding: 0;}ul {list-style: none;width: 2400px;}#box {width: 1200px;height: 400px;border: 2px solid red;margin: 100px auto;overflow: hidden;}#box li {width: 240px;height: 400px;float: left;}</style>
</head><body><div id="box"><ul><li><img src="./images/collapse/1.jpg" alt=""></li><li><img src="./images/collapse/2.jpg" alt=""></li><li><img src="./images/collapse/3.jpg" alt=""></li><li><img src="./images/collapse/4.jpg" alt=""></li><li><img src="./images/collapse/5.jpg" alt=""></li></ul></div><script src="./animation.js"></script><script>/*需求(1):给每一个li设置鼠标移入事件:当前li的宽度变成800,其他兄弟li宽度变成100(2):鼠标移出大盒子,所有的li的宽度都变成默认的240 *///1.获取元素var liList = document.querySelectorAll('#box li');//li元素列表var box = document.querySelector('#box');//li元素列表/* 一:声明全局变量存储定时器ID */var timeID = null;//2.注册事件//2.1 鼠标移入事件:当前li的宽度变成800,其他兄弟li宽度变成100for (var i = 0; i < liList.length; i++) {liList[i].onmouseover = function () {//二:先清除以前的定时器,以本次为准clearTimeout(timeID);//事件处理函数 : this 指向事件源/* 三:当事件被触发时,用户可能是误操作,所以开启定时器等一会儿再执行注意点: 定时器中的this默认一定是window,需要动态修改为事件源*/timeID = setTimeout(function () {console.log(1111);// 定时器中的this : 默认指向window//3.排他思想修改样式for (var j = 0; j < liList.length; j++) {if (liList[j] == this) {//是自己animationSlow(liList[j], { width: 800 });} else {animationSlow(liList[j], { width: 100 });}};}.bind(this), 500);};};//2.2 鼠标移出大盒子,所有的li的宽度都变成默认的240 box.onmouseout = function (e) {/* 由于受到事件冒泡影响,当鼠标滑出某一个li元素也会触发父元素的移出事件解决方案:判断事件触发源是不是box,是的话才修改li元素宽度为240*/if (e.target == box) {for (var i = 0; i < liList.length; i++) {animationSlow(liList[i], { width: 240 });};};};</script></body></html>

3.万能防抖函数的封装

  • 为什么要封装万能的防抖函数
    • 在上一个小节中,我们的重点是介绍函数防抖的思路。但是在实际开发中,每一个防抖函数的事件处理都是不一样的,他们可能是鼠标移入、鼠标移出、鼠标移动。 每一个案例需要的防抖间隔也不同
/**
* @description: 万能防抖函数
* @param {type} fn : 事件处理函数
* @param {type} timeout : 防抖时间间隔
* @return: 
*/
function debounce(fn, timeout) {/*核心技术介绍 1. 函数防抖需要使用定时器,但是定时器id不能是局部的  (局部变量函数执行完毕会被回收)2. 定时器id如果使用全局变量存储,则会造成全局变量污染3. 解决方案 :(1)使用闭包延长局部变量声明周期,但是语法过于繁琐(2)利用函数本身也是对象,使用函数本身的静态成员来存储定时器id*///1.先清除上一次触发事件的定时器clearTimeout(debounce.timeID);//2.以最后一次触发为准debounce.timeID = setTimeout(fn, 500);
};
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>动画-案例《手风琴》</title><style>* {margin: 0;padding: 0;}ul {list-style: none;width: 2400px;}#box {width: 1200px;height: 400px;border: 2px solid red;margin: 100px auto;overflow: hidden;}#box li {width: 240px;height: 400px;float: left;}</style>
</head><body><div id="box"><ul><li><img src="./images/collapse/1.jpg" alt=""></li><li><img src="./images/collapse/2.jpg" alt=""></li><li><img src="./images/collapse/3.jpg" alt=""></li><li><img src="./images/collapse/4.jpg" alt=""></li><li><img src="./images/collapse/5.jpg" alt=""></li></ul></div><script src="./animation.js"></script><script>/*需求(1):给每一个li设置鼠标移入事件:当前li的宽度变成800,其他兄弟li宽度变成100(2):鼠标移出大盒子,所有的li的宽度都变成默认的240 *///1.获取元素var liList = document.querySelectorAll('#box li');//li元素列表var box = document.querySelector('#box');//li元素列表//2.注册事件//2.1 鼠标移入事件:当前li的宽度变成800,其他兄弟li宽度变成100for (var i = 0; i < liList.length; i++) {liList[i].onmouseover = function () {debounce(function () {for (var j = 0; j < liList.length; j++) {if (liList[j] == this) {//是自己animationSlow(liList[j], { width: 800 });} else {animationSlow(liList[j], { width: 100 });}};}.bind(this), 500);};};/*** @description: 万能防抖函数* @param {type} fn : 事件处理函数* @param {type} timeout : 防抖时间间隔* @return: */function debounce(fn, timeout) {/*核心技术介绍 1. 函数防抖需要使用定时器,但是定时器id不能是局部的  (局部变量函数执行完毕会被回收)2. 定时器id如果使用全局变量存储,则会造成全局变量污染3. 解决方案 :(1)使用闭包延长局部变量声明周期,但是语法过于繁琐(2)利用函数本身也是对象,使用函数本身的静态成员来存储定时器id*///1.先清除上一次触发事件的定时器clearTimeout(debounce.timeID);//2.以最后一次触发为准debounce.timeID = setTimeout(fn, 500);};//2.2 鼠标移出大盒子,所有的li的宽度都变成默认的240 box.onmouseout = function (e) {/* 由于受到事件冒泡影响,当鼠标滑出某一个li元素也会触发父元素的移出事件解决方案:判断事件触发源是不是box,是的话才修改li元素宽度为240*/if (e.target == box) {for (var i = 0; i < liList.length; i++) {animationSlow(liList[i], { width: 240 });};};};</script></body></html>

这篇关于网页性能优化03-函数防抖的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1130392

相关文章

Pandas中统计汇总可视化函数plot()的使用

《Pandas中统计汇总可视化函数plot()的使用》Pandas提供了许多强大的数据处理和分析功能,其中plot()函数就是其可视化功能的一个重要组成部分,本文主要介绍了Pandas中统计汇总可视化... 目录一、plot()函数简介二、plot()函数的基本用法三、plot()函数的参数详解四、使用pl

一文教你Python如何快速精准抓取网页数据

《一文教你Python如何快速精准抓取网页数据》这篇文章主要为大家详细介绍了如何利用Python实现快速精准抓取网页数据,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录1. 准备工作2. 基础爬虫实现3. 高级功能扩展3.1 抓取文章详情3.2 保存数据到文件4. 完整示例

python获取网页表格的多种方法汇总

《python获取网页表格的多种方法汇总》我们在网页上看到很多的表格,如果要获取里面的数据或者转化成其他格式,就需要将表格获取下来并进行整理,在Python中,获取网页表格的方法有多种,下面就跟随小编... 目录1. 使用Pandas的read_html2. 使用BeautifulSoup和pandas3.

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

MySQL索引的优化之LIKE模糊查询功能实现

《MySQL索引的优化之LIKE模糊查询功能实现》:本文主要介绍MySQL索引的优化之LIKE模糊查询功能实现,本文通过示例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前缀匹配优化二、后缀匹配优化三、中间匹配优化四、覆盖索引优化五、减少查询范围六、避免通配符开头七、使用外部搜索引擎八、分

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序