防抖和节流是我们常用的优化交互手段,防抖是在n 秒后再执行该事件,若在 n 秒内被重复触发,则重新计时
节流是n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效。不论哪一种我们之前都是通过js来实现的,现在
css也能轻松实现节流的功能,下面来带大家一起看一下。
CSS动画实现思路分析
CSS实现的思维肯定跟JS是大不相同的,我们思考一下节流本质上就是对一个点击事件的限制,而且这个限制是和时间相关联的。
那么如何让CSS对点击事件产生限制呢?没错就是pointer-events
接下来还要跟时间关联,比如每次点击要禁用0.5秒,0.5秒后再恢复,很容易联想到动画animation
最后还要绑定触发时机,CSS可没有点击事件,但是有伪类:active
我们确定了要用的核心属性之后,就可以考虑如果把他们组合起来实现节流了。
其实这种场景可以理解成是对 CSS 动画的控制,比如有一个动画控制按钮从禁用->可点击的变化,每次点击时让这个动画重新执行一遍,在执行的过程中,一直处于禁用状态,是不是就达到了“节流”的效果了?
动画实现方案
首先我们需要一个触发的按钮,然后定义一段关键帧动画,再把这段动画绑定到按钮上。
这里动画的缓动函数设置成了阶梯曲线,step-end,它可以很方便的控制pointer-events的变化时间点。
<button onclick="console.log('触发')">按钮</button>
<style>
button{
animation: throttle 3s step-end forwards;
}
button:active{
animation: none;
}
@keyframes throttle {
from {
color:red;
pointer-events: none;
}
to {
color:green;
pointer-events: all;
}
}
</style>
这里大家可能第一次接触step和 forwards属性,这里简单说明下含义
如下图所示step不同于其它连续流畅的缓动函数,它是顿挫执行的。
steps(number, position)有两个参数
第一个number表示把我们的动画分成了多少段
第二个position表示动画是从时间段的开头连续还是末尾连续
step-end是steps()功能符简化关键字,等同于steps(1, end)。用中文解释一下就动画一步到位的意思。
forwards是当动画完成后,保持最后一帧的状态(也就是最后一个关键帧中定义的状态)
对应这个demo就是文字变绿且可触发事件。以上就是用动画实现节流的一种方案。其实还有另一种实现方式,不过要稍微借助一下js。
transition实现方案
这种方案的实现思路是通过:active去触发transition变化,然后通过监听transition回调去动态设置按钮的禁用状态
<button onclick="console.log('触发')">按钮</button>
<style>
button{
opacity: .99;
transition: opacity 3s;
}
button:not(:disabled):active{
opacity: 1;
transition: 0s;
}
</style>
<script>
// 过渡开始
document.addEventListener('transitionstart', function(e){
e.target.disabled = true
})
// 过渡结束
document.addEventListener('transitionend', function(e){
e.target.disabled = false
})
</script>
这里的opacity是随意设置的一个属性,单纯为了配合transition的效果。3秒内透明度从0.99变成1,然后用js给这个带transition的button加监听事件,当过渡效果开始的时候直接禁用按钮,过渡效果结束的时候消除禁用,这样就实现了节流的效果。
这种方案好处是可以使用按钮的原生禁用效果,用户体验要更好。
浏览器兼容性
总结
用css来实现节流相比纯js的方式要精简、使用更简单,没有框架限制。以上两种方案实现节流的逻辑都和业务逻辑能最大程度上的解耦。
但是这种实现方式还是比较有局限的,仅限于点击行为,像很多时候,节流可能会用在滚动事件或者键盘事件上,像这些场景就只用传统的方式去实现了。