精品一区二区三区在线成人,欧美精产国品一二三区,Ji大巴进入女人66h,亚洲春色在线视频

還在用 JS 做節(jié)流嗎?CSS 也可以防止按鈕重復(fù)點(diǎn)擊

開發(fā) 前端
CSS 實(shí)現(xiàn)“節(jié)流”其實(shí)就是控制一個(gè)動畫的精準(zhǔn)控制,假設(shè)有一個(gè)動畫控制按鈕從禁用->可點(diǎn)擊的變化,每次點(diǎn)擊時(shí)讓這個(gè)動畫重新執(zhí)行一遍,在執(zhí)行的過程中,一直處于禁用狀態(tài),這樣就達(dá)到了“節(jié)流”的效果。

眾所周知,函數(shù)節(jié)流(throttle)是 JS 中一個(gè)非常常見的優(yōu)化手段,可以有效的避免函數(shù)過于頻繁的執(zhí)行。

舉個(gè)例子:一個(gè)保存按鈕,為了避免重復(fù)提交或者服務(wù)器考慮,往往需要對點(diǎn)擊行為做一定的限制,比如只允許每300ms提交一次,這時(shí)候我想大部分同學(xué)都會到網(wǎng)上直接拷貝一段throttle函數(shù),或者直接引用lodash工具庫。

btn.addEventListener('click', _.throttle(save, 300))

其實(shí)除了 JS 方式, CSS 也可以非常輕易的實(shí)現(xiàn)這樣一個(gè)功能,無需任何框架庫,一起看看吧!

一、CSS 實(shí)現(xiàn)思路分析

CSS 實(shí)現(xiàn)和 JS 的思維不同,需要從另一個(gè)角度去看待這個(gè)問題。

比如這里的需要對點(diǎn)擊事件進(jìn)行限制,也就是禁用點(diǎn)擊事件,想想有什么方式可以禁用事件,沒錯,就是pointer-events;

然后是時(shí)間的限制,每次點(diǎn)擊后需要自動禁用300ms,時(shí)間過后重新恢復(fù),那么,有什么特性和時(shí)間以及狀態(tài)恢復(fù)有關(guān)呢?沒錯,就是animation;

除此之外,還需要有觸發(fā)時(shí)機(jī),這里是點(diǎn)擊行為,所以必然和偽類:active有關(guān)聯(lián)。

因此,綜合分析,實(shí)現(xiàn)這樣一個(gè)功能需要用到pointer-events、animation以及:active,那么如何將這些思路串聯(lián)起來呢?

圖片

思考3秒...

??

??

??

你想到了嗎???????

其實(shí)這種場景可以理解成是對 CSS 動畫的控制,比如有一個(gè)動畫控制按鈕從禁用->可點(diǎn)擊的變化,每次點(diǎn)擊時(shí)讓這個(gè)動畫重新執(zhí)行一遍,在執(zhí)行的過程中,一直處于禁用狀態(tài),是不是就達(dá)到了“節(jié)流”的效果了?

接下來看看具體實(shí)現(xiàn)

二、CSS 動畫的精準(zhǔn)控制

假設(shè)有一個(gè)按鈕,綁定了一個(gè)點(diǎn)擊事件。

<button notallow="console.log('保存')">保存</button>

這時(shí)的按鈕連續(xù)點(diǎn)擊就會不斷地觸發(fā),效果如下:

圖片

下面定義一個(gè)關(guān)于pointer-events的動畫,就叫做 throttle 吧!

@keyframes throttle {
from {
pointer-events: none;
}
to {
pointer-events: all;
}
}

很簡單吧,就是從禁用到可點(diǎn)擊的變化。

接下來,將這個(gè)動畫綁定在按鈕上,這里為了方便測試,將動畫設(shè)置成了2s。

button{
animation: throttle 2s step-end forwards;
}

注意,這里動畫的緩動函數(shù)設(shè)置成了階梯曲線,step-end,它可以很方便的控制pointer-events的變化時(shí)間點(diǎn)。

有興趣的可以參考這篇文章:CSS3 animation屬性中的steps功能符深入介紹 ? 張鑫旭-鑫空間-鑫生活 (zhangxinxu.com)[1]。

如下示意,pointer-events在0~2秒內(nèi)的值都是none,一旦到達(dá)2秒,就立刻變成了all,由于是forwards,會一直保持all的狀態(tài)。

圖片

最后,在點(diǎn)擊時(shí)重新執(zhí)行一遍動畫,只需要在按下時(shí)設(shè)置動畫為none就行了。

這個(gè)技巧之前在這篇文章中有更詳細(xì)的介紹:CSS 實(shí)現(xiàn)按鈕點(diǎn)擊動效的套路。

實(shí)現(xiàn)如下:

button:active{
animation: none;
}

為了演示方便,我們暫時(shí)把顏色變化也加在動畫里。

@keyframes throttle {
from {
color: red;
pointer-events: none;
}
to {
color: green;
pointer-events: all;
}
}

現(xiàn)在如果文字是red,表示是禁用態(tài),只有是green,才表示可以被點(diǎn)擊,非常清晰明了,如下:

圖片

下面是最終點(diǎn)擊對比效果,很好地限制了點(diǎn)擊頻率。

圖片

完整代碼如下,就這么幾行,如果需要改限制時(shí)間,直接改動畫時(shí)間就行了。

button{
animation: throttle 2s step-end forwards;
}
button:active{
animation: none;
}
@keyframes throttle {
from {
pointer-events: none;
}
to {
pointer-events: all;
}
}

你也可以查看以下任意鏈接:

  • CSS throttle (codepen.io)[2]
  • CSS throttle - 碼上掘金 (juejin.cn)[3]
  • CSS throttle (runjs.work)[4]

三、CSS 實(shí)現(xiàn)的其他思路

借用這種思路,也可以很輕松的實(shí)現(xiàn)節(jié)流的效果。而且為了更好的體驗(yàn),可以用上真正的按鈕禁用。

btn.disabled = true

具體思路是這樣的,通過:active去觸發(fā)transition變化,然后通過監(jiān)聽transition回調(diào)去動態(tài)設(shè)置按鈕的禁用狀態(tài),實(shí)現(xiàn)如下:

定義一個(gè)無關(guān)緊要的過渡屬性,比如opacity。

button{
opacity: .99;
transition: opacity 2s;
}
button:not(:disabled):active{
opacity: 1;
transition: 0s;
}

然后監(jiān)聽transition的起始回調(diào)。

// 過渡開始
document.addEventListener('transitionstart', function(ev){
ev.target.disabled = true
})
// 過渡結(jié)束
document.addEventListener('transitionend', function(ev){
ev.target.disabled = false
})

這樣做的最大好處是,這部分禁用的邏輯是完全和業(yè)務(wù)邏輯是解耦的,可以在任意時(shí)候,任意場合下無縫接入,也不受框架和環(huán)境影響,效果如下

圖片

完整代碼也可以查看以下任意鏈接:

  • CSS throttle disabled (codepen.io)[5]
  • CSS throttle disabled - 碼上掘金 (juejin.cn)[6]
  • CSS throttle disabled (runjs.work)[7]

四、總結(jié)一下

以上通過 CSS 的思路實(shí)現(xiàn)了類似“節(jié)流”的功能,相比 JS 實(shí)現(xiàn)而言,實(shí)現(xiàn)更精簡、使用更簡單,沒有框架限制,下面一起總結(jié)一下實(shí)現(xiàn)要點(diǎn):

  • 函數(shù)節(jié)流是一個(gè)非常常見的優(yōu)化方式,可以有效避免函數(shù)過于頻繁的執(zhí)行。
  • CSS 的實(shí)現(xiàn)思路和 JS 不同,重點(diǎn)在于在于找到和該場景相關(guān)聯(lián)的屬性。
  • CSS 實(shí)現(xiàn)“節(jié)流”其實(shí)就是控制一個(gè)動畫的精準(zhǔn)控制,假設(shè)有一個(gè)動畫控制按鈕從禁用->可點(diǎn)擊的變化,每次點(diǎn)擊時(shí)讓這個(gè)動畫重新執(zhí)行一遍,在執(zhí)行的過程中,一直處于禁用狀態(tài),這樣就達(dá)到了“節(jié)流”的效果。
  • 還可以通過 transition 的回調(diào)函數(shù)動態(tài)設(shè)置按鈕禁用態(tài)。
  • 這種實(shí)現(xiàn)的好處在于禁用邏輯和業(yè)務(wù)邏輯是完全解耦的。

不過,這種實(shí)現(xiàn)方式還是比較有局限的,僅限于點(diǎn)擊行為,像很多時(shí)候,節(jié)流可能會用在滾動事件或者鍵盤事件上,像這些場景就用傳統(tǒng)方式實(shí)現(xiàn)就行了。

參考資料

[1] CSS3 animation屬性中的steps功能符深入介紹 ? 張鑫旭-鑫空間-鑫生活 (zhangxinxu.com?): https://www.zhangxinxu.com/wordpress/2018/06/css3-animation-steps-step-start-end/

[2] CSS throttle (codepen.io): https://codepen.io/xboxyan/pen/rNKmmVq

[3] CSS throttle - 碼上掘金 (juejin.cn): https://code.juejin.cn/pen/7164961819369570345

[4] CSS throttle (runjs.work): https://runjs.work/projects/47885939389440f4

[5] CSS throttle disabled (codepen.io): https://codepen.io/xboxyan/pen/oNyWwvB

[6] CSS throttle disabled - 碼上掘金 (juejin.cn): https://code.juejin.cn/pen/7164994189032161311

[7] CSS throttle disabled (runjs.work): https://runjs.work/projects/41e8b998624743fc

責(zé)任編輯:武曉燕 來源: 前端偵探
相關(guān)推薦

2022-12-26 08:25:16

CSS函數(shù)節(jié)流

2024-11-12 16:28:34

2024-08-15 08:56:17

2012-07-19 10:03:32

2024-10-11 16:34:22

2022-09-13 17:54:55

CSS定時(shí)器監(jiān)聽事件

2021-11-02 16:44:40

部署DevtoolsJRebel

2021-12-06 17:44:56

MHAMySQL高可用

2021-01-03 17:14:16

ORMObjective S運(yùn)行

2020-03-04 14:05:35

戴爾

2014-09-12 17:55:42

2022-05-05 09:14:41

AlpineDocker鏡像開發(fā)

2020-03-10 10:37:48

數(shù)據(jù)丟失數(shù)據(jù)泄露網(wǎng)絡(luò)安全

2025-04-02 08:47:23

DOM文檔結(jié)構(gòu)API

2018-05-29 10:20:50

人工智能機(jī)器人計(jì)算機(jī)

2015-08-27 09:30:38

2025-09-08 04:00:00

2024-06-03 00:00:06

高性能數(shù)據(jù)傳輸應(yīng)用程序

2020-02-11 11:37:37

比特幣區(qū)塊鏈加密

2011-05-04 13:28:07

噴墨打印機(jī)供墨
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 西乡县| 扬中市| 汕尾市| 九龙城区| 台中市| 太康县| 高碑店市| 新邵县| 临漳县| 当涂县| 德昌县| 子长县| 邯郸县| 龙江县| 贵溪市| 瓮安县| 云南省| 易门县| 红原县| 遂溪县| 东乡县| 蓝田县| 镇平县| 台山市| 郸城县| 苗栗县| 安宁市| 兴城市| 遵义县| 巴彦淖尔市| 施秉县| 平罗县| 马鞍山市| 平利县| 芒康县| 大城县| 阿巴嘎旗| 涪陵区| 兰州市| 福泉市| 巴塘县|