重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
在前端开发中,经常和 DOM 、 BOM 打交道,例如:窗口的resize、scroll,输入框内容校验,按钮点击等等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕。此时我们可以采用 throttle(节流) 和 debounce(防抖) 的方式来减少调用频率,提高性能的同时又不影响实际效果。
创新互联公司为企业级客户提高一站式互联网+设计服务,主要包括做网站、网站制作、成都App制作、成都微信小程序、宣传片制作、LOGO设计等,帮助客户快速提升营销能力和企业形象,创新互联各部门都有经验丰富的经验,可以确保每一个作品的质量和创作周期,同时每年都有很多新员工加入,为我们带来大量新的创意。
实现方式: 每次触发事件时,如果当前有等待执行的延时函数,则直接return。
区别 : 节流函数 不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而 防抖函数 只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。
Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。其中就封装好了节流函数 throttle 和防抖函数 debounce 。
参数:
返回: (Function): 返回 节流 的函数。
例子:
参数:
返回: (Function): 返回新的 debounced (防抖动)函数。
例子:
1.节流 :使得一定时间内只触发一次函数。原理是通过判断是否有延迟调用函数未执行。
2.防抖 :将多次操作合并为一次操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。
欢迎访问: 天问博客
在进行窗口的resize、scroll,输入框内容校验,防止按钮重复点击等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,体验糟糕。所以可以采用debounce(防抖)和throttle(节流)的方式来减少调用频率,同时又不影响实际效果。
我们一起先来看看防抖和节流的区别
防抖函数 debounce
节流函数 throttle
如何调用
防抖和节流都利用了闭包,首先就调用了debounce和debounce方法,把内部的方法返回出去,下次自己执行,以后有时间我再写一下闭包吧,所以我还留下一个问题,这样会不会造成内存泄漏?
节流概念(Throttle)
按照设定的时间固定执行一次函数,比如200ms一次。注意:固定就是你在mousemove过程中,执行这个节流函数,它一定是200ms(你设定的定时器延迟时间)内执行一次。没到200ms,一定会返回,没有执行回调函数的。
主要应用场景有:scroll、touchmove
防抖概念(Debounce)
抖动停止后的时间超过设定的时间时执行一次函数。注意:这里的抖动停止表示你停止了触发这个函数,从这个时间点开始计算,当间隔时间等于你设定时间,才会执行里面的回调函数。如果你一直在触发这个函数并且两次触发间隔小于设定时间,则一定不会到回调函数那一步。·
主要应用场景有:input验证、搜索联想、resize
节流实现
思路: 第一次先设定一个变量true,第二次执行这个函数时,会判断变量是否true,是则返回。当第一次的定时器执行完函数最后会设定变量为flase。那么下次判断变量时则为flase,函数会依次运行。
防抖实现
思路:首次运行时把定时器赋值给一个变量,第二次执行时,如果间隔没超过定时器设定的时间则会清除掉定时器,重新设定定时器,依次反复,当我们停止下来时,没有执行清除定时器,超过一定时间后触发回调函数。
博文有介绍更详细的原理和代码demo:网页链接,希望可以帮到您
节流函数是防止短时间内多次触发的一个处理函数
如:滚动事件,使用 addEventListener 方式添加监听器
为了使节流之后滚动更加的平滑, 我们可以使用 window.requestAnimationFrame() 来实现节流函数
在视窗中显示
当需要实现图片的懒加载或者是无限滚动时,需要确定元素是否出现在视窗中, 这样需要获取 elem.getBoundingClientRect();
注意: 每次调用 getBoundingClientRect 时都会触发回流, 这样会严重的影响性能,特别是在事件处理函数中,会更加的严重影响性能;
在 2016 年之后, 可以通过 Intersection Observer 这个 api 来解决问题, 它允许你追踪目标元素与其祖先元素或者视窗的交叉状态, 另外只有一部分元素出现在视窗中,哪怕只有 1 px , 也可以选择触发回调函数
滚动边界的问题:
当用户滚到末尾时, 整个页面都会开始滚动;
连锁滚动的表现, 当滚动有;元素到达底部时,可以改变页面的 overflow 属性或者在滚动元素的滚动事件处理函数中取消默认行为来解决这个问题
如果使用 JavaScript 处理, 那么处理的不是 scroll 事件, 而是每当用户使用鼠标滚轮 或者 是触摸板时 触发的是 wheel 事件
过度滚动对移动端的影响尤为的严重,下拉刷新的手势在 安卓的chrome 浏览器中,问题出现了,它会刷新整个页面, 而不是加载更多的内容;这个就会产生很多问题;
css 通过 overscroll-behavior 这个新属性解决问题。它通过控制元素滚动到尽头时的行为来解决 下拉刷新与 连锁滚动带来的问题。安卓的 glow 与苹果中的 rubber band。
准确的说, IE 与 Edge 实现了独有的 -ms-scroll-chaining 属性来控制连锁滚动;
微软浏览器已经准备实现 overscroll-behavior 这个属性
在触屏设备上,滚动的体验是一个很大的话题。
苹果公司开发了 惯性 滚动的专利;
css 有一个很hack 的方法;
只支持 webkit 内核,
但是我们会使用 touch 事件来解决这个问题,但是这个会对用户滚动体验造成很大的影响;
在现代的浏览器中,虽然知道如何使滚动变得平滑,但为了 确定滚动事件处理函数中是否执行了 阻止默认事件 ;可能任会花费 500 mm 来等待事件处理函数执行完毕
即使是一个空的事件监听函数, 从不取消任何行为,鉴于浏览器会期待 preventDefault 的调用, 也会对性能造成影响
为了告诉浏览器不去检测事件是否阻止了默认事件,在 whatwg dom 标准中,存在一个特性,来解决这个事件,
这个视频会看到带来的性能提升:
此文借鉴: