摘要:是一門(mén)很神奇的語(yǔ)言,很多和它不相干的功能卻能起到很顯著的效果,有些在看起來(lái)實(shí)現(xiàn)都有一定的工作量,一句屬性就能輕而易舉的解決,下面來(lái)看幾個(gè)例子主要和事件相關(guān)。那么,如何借助來(lái)監(jiān)聽(tīng)這些呢可以從過(guò)渡和動(dòng)畫(huà)兩個(gè)思路來(lái)考慮。
CSS是一門(mén)很神奇的語(yǔ)言,很多和它不相干的功能卻能起到很顯著的效果,有些在js看起來(lái)實(shí)現(xiàn)都有一定的工作量,CSS一句屬性就能輕而易舉的解決,下面來(lái)看幾個(gè)例子(主要和js事件相關(guān))。
原鏈接
https://notes.codelabo.cn/art...
原issues
https://github.com/XboxYan/no...
很多都是開(kāi)腦洞想出來(lái)的,實(shí)現(xiàn)效果卻意外的驚人事件禁用
在js中對(duì)事件禁用并不復(fù)雜,但是卻容易影響到業(yè)務(wù)邏輯
function buy(){ if(XX){ return false; } //其他業(yè)務(wù)代碼 }
當(dāng)然,元素也要設(shè)置相應(yīng)的樣式,讓它看起來(lái)不可點(diǎn)擊。
css對(duì)事件禁用就比較簡(jiǎn)單了,主要有兩種方式
1. disabled
原生表單元素是有默認(rèn)的禁用屬性的,比如
可以看出,禁用的默認(rèn)樣式為
button:disabled { color: graytext; }
所以,在這里你可以隨意的修改禁用的樣式
button:disabled { color: red; } button[disabled] {/**屬性選擇器也行**/ color: red; } button:hover { /**:hover支持**/ color: red; } button:active,button:focus{/**不支持,其實(shí)也好理解,會(huì)觸發(fā)focus()事件,所以也禁用了**/ color:red }
一般情況下,使用這種方式是比較好的,天然的禁用屬性,兼容性也不錯(cuò)
2. pointer-events:none
這個(gè)屬性應(yīng)該也不陌生,最常見(jiàn)的用法就是禁用一個(gè)按鈕,而且不局限于表單元素,任意元素均可(比如很多人喜歡用的a標(biāo)簽)
button.disabled { pointer-events:none; user-select:none;/*去除選中效果*/ color: graytext; }
這個(gè)屬性用處很多,很多js絞盡腦汁想要過(guò)濾掉的方法,直接就用一行屬性解決,這里就不展開(kāi)了,網(wǎng)上教程很多。
查看這個(gè)demo
長(zhǎng)按事件原生js中并沒(méi)有長(zhǎng)按事件,通常開(kāi)發(fā)者一般會(huì)順著思路,使用定時(shí)器來(lái)完成
下面是偽代碼
el.onmousedown = function(){ this.timer && clearTimeout(this.timer); this.timer = settimeout(function(){ //業(yè)務(wù)代碼 },350) } el.onmouseup = function(){ this.timer && clearTimeout(this.timer); }
當(dāng)然,可以借助css來(lái)完成,而且效果更好,易于控制
這里為什么說(shuō)是“借助”呢,因?yàn)椴荒芡耆衏ss來(lái)完成,只是利用了某些特性
css3中新增了過(guò)渡和動(dòng)畫(huà)屬性,與之相對(duì)應(yīng)的也預(yù)設(shè)了這些動(dòng)畫(huà)的回調(diào)事件,如下
事件 | 說(shuō)明 |
---|---|
transitionstart | 在開(kāi)始過(guò)渡時(shí)觸發(fā) |
transitionrun | 在進(jìn)行過(guò)渡時(shí)觸發(fā) |
transitioncancel | 在取消過(guò)渡時(shí)觸發(fā) |
transitionend | 在完成過(guò)渡后觸發(fā) |
animationstart | 在 animation 開(kāi)始時(shí)觸發(fā) |
animationiteration | 在 animation 完成一個(gè)周期時(shí)觸發(fā) |
animationend | 在 animation 完成時(shí)觸發(fā) |
animationcancel | 在 animation 取消時(shí)觸發(fā) |
有些事件存在兼容性問(wèn)題,有興趣的可以詳細(xì)研究
有了這些事件,要做一個(gè)長(zhǎng)按事件就很容易了,這里有兩種種思路,大家可以腦洞一下
假設(shè)需要延時(shí)1s;
過(guò)渡時(shí)間設(shè)置為1s,調(diào)用transitionend或者animationend
延時(shí)1s,調(diào)用transitionstart或者animationstart
這里以第一種情況transitionend(過(guò)渡比動(dòng)畫(huà)實(shí)現(xiàn)要容易多,代碼也少,優(yōu)先用過(guò)渡)來(lái)實(shí)現(xiàn)
button:hover:active{ opacity:.99;/**隨便選取一個(gè)不影響頁(yè)面的可以過(guò)渡的樣式**/ transition:opacity 1s; }
相應(yīng)的,js需要監(jiān)聽(tīng)transitionend事件,不需要借助定時(shí)器(個(gè)人有點(diǎn)鄙視定時(shí)器的思想^)
el.addEventListener("transitionend",function(){ //業(yè)務(wù)代碼 })
是不是精簡(jiǎn)很多呢,需要改長(zhǎng)按時(shí)間可以直接通過(guò)css來(lái)控制
這里封裝了一下自定義事件,可以更好的在項(xiàng)目中使用(雖然代碼本身就很少了)。
查看這個(gè)demo
單次點(diǎn)擊事件在jquery中有一個(gè)once(好像是這個(gè))方法,表示綁定一次性事件,點(diǎn)擊一次后就不再生效。
原生js實(shí)現(xiàn)這個(gè)也不復(fù)雜,通常做法就是定義一個(gè)標(biāo)識(shí),點(diǎn)擊后改變一下,下面是偽代碼
el.onclick = function(){ if(!this.once){ //業(yè)務(wù)代碼 this.once = true; } }
借助上面的思路,css也可以實(shí)現(xiàn)類(lèi)似的效果,深究了一番,總結(jié)以下兩個(gè)方法
1.animationend
animationend是動(dòng)畫(huà)結(jié)束后觸發(fā),顯然我們可以在這里做文章
比如我們可以在初始狀態(tài)給一個(gè)暫停狀態(tài)animation-play-state:paused,然后在點(diǎn)擊時(shí)運(yùn)動(dòng)animation-play-state:running,結(jié)束后一直保持在最后狀態(tài)animation-fill-mode: forwards
.button{ animation: once .01s paused forwards;/**給一個(gè)足夠小的運(yùn)動(dòng)時(shí)間,確保能夠在`:active`時(shí)運(yùn)動(dòng)完成**/ } .button:hover:active{ animation-play-state:running; } @keyframes once { to{ opacity:.8; } }
js只需要對(duì)animationend進(jìn)行監(jiān)聽(tīng)
el.addEventListener("animationend",function(){ //業(yè)務(wù)代碼 })
2.純css實(shí)現(xiàn)
不知道在上面的例子中有沒(méi)有發(fā)現(xiàn),在動(dòng)畫(huà)結(jié)束時(shí)把元素禁用會(huì)怎么樣?
@keyframes once { to{ opacity:.8; pointer-events:none; user-select:none; } }
這樣就可以在運(yùn)動(dòng)完直接禁用,好像很完美?
事實(shí)上,這里運(yùn)動(dòng)的時(shí)間很難把控,大家都知道,onclick其實(shí)是包含按下和抬起兩個(gè)過(guò)程的,如果抬起的太慢,那么此時(shí)元素已經(jīng)禁用了,觸發(fā)不了事件;如果抬起太快,如果快速點(diǎn)擊,由于還沒(méi)運(yùn)動(dòng)完成,會(huì)觸發(fā)多次事件。
解決方式也很簡(jiǎn)單,用onmousedown代替即可
查看這個(gè)demo
onresize事件大家都知道window有個(gè)onresize事件,可以在窗口拉伸的時(shí)候觸發(fā),然后就能實(shí)時(shí)獲取窗體的尺寸等等屬性。
window.onresize = function(ev){ //業(yè)務(wù)代碼 }
但是,普通的元素卻沒(méi)有這個(gè)監(jiān)聽(tīng),比如
div.onresize = function(ev){ //不生效... }
為什么需要這個(gè)功能呢?
大家可能知道有這樣一個(gè)屬性,可以原生拉伸元素,改變尺寸
.box{ overflow: hidden;/**需要配合overflow才能生效**/ resize: both; }
只需一個(gè)屬性,就可以實(shí)現(xiàn)元素的拉伸(雖然稍有瑕疵),不需要大量的js來(lái)計(jì)算。
視覺(jué)展示還好,但是如果需要實(shí)時(shí)知道元素的尺寸怎么辦呢,js通常有兩種思路
1. onmousemove事件
拉伸的時(shí)候很自然的想到是有鼠標(biāo)按住然后拖拽完成,所以可以給元素添加onmouse-*一系列事件,同時(shí)要注意鼠標(biāo)抬起要取消監(jiān)聽(tīng)
//大概是這樣的邏輯 div.onmousedown = function(){ div.onmousemove = fn;//監(jiān)聽(tīng) div.onmouseup = function(){ div.onmousemove = null; } }
2. 定時(shí)器
借助setInterval或者requestAnimFrame來(lái)實(shí)現(xiàn)監(jiān)聽(tīng),同樣是需要注意取消監(jiān)聽(tīng)的時(shí)機(jī)
//大概是這樣的邏輯 div.onmousedown = function(){ this.timer && clearInterval(this.timer) this.timer = setInterval(fn,300);//監(jiān)聽(tīng) div.onmouseup = function(){ this.timer && clearInterval(this.timer) } }
很顯然,上面的方法都不是特別的舒適,很多情況下都會(huì)出現(xiàn)監(jiān)聽(tīng)取消的問(wèn)題,導(dǎo)致不停的觸發(fā),影響體驗(yàn)。
這時(shí)候,又輪到css出場(chǎng)了,很多時(shí)候js覺(jué)得實(shí)現(xiàn)起來(lái)不順暢的時(shí)候都可以用css的思維來(lái)重新認(rèn)識(shí)。
那么,如何借助css來(lái)監(jiān)聽(tīng)這些呢?
可以從過(guò)渡和動(dòng)畫(huà)兩個(gè)思路來(lái)考慮。
1. CSS過(guò)渡
首先,我們可以知道的是,在通過(guò)resize: both進(jìn)行元素拉伸的時(shí)候,改變的是width和height,這一點(diǎn)可以從開(kāi)發(fā)者工具直接看到
我們需要通過(guò)transitionrun或者transitionend來(lái)監(jiān)聽(tīng)width和height,所以需要給這兩個(gè)屬性加上過(guò)渡
.box{ transition:width .3s,ehight .3s;//分別給width和height設(shè)置過(guò)渡,其他屬性不需要 }
這樣就可以拿到監(jiān)聽(tīng)了,不過(guò)這種方式有一個(gè)弊端,由于過(guò)渡需要時(shí)間,所以有一種不跟隨,卡頓的感覺(jué)。
所以我們來(lái)看第二種方式
2. animationiteration
css動(dòng)畫(huà)可以設(shè)置播放次數(shù),如果設(shè)置成animation-iteration-count: infinite就表示無(wú)限輪播,配合animationiteration回調(diào),不就可以實(shí)現(xiàn)監(jiān)聽(tīng)了么
.box:active{ animation: resize .3s infinite forwards; } @keyframes resize{ to { opacity: .99;/**用一個(gè)無(wú)關(guān)緊要的屬性來(lái)觸發(fā)動(dòng)畫(huà)**/ } }
js很簡(jiǎn)單,一個(gè)監(jiān)聽(tīng)就能解決問(wèn)題,也不需要什么取消監(jiān)聽(tīng)什么,這些都已經(jīng)在css完成了
el.addEventListener("animationiteration",function(){ //業(yè)務(wù)代碼 })
這里是每個(gè)動(dòng)畫(huà)完成一次就回調(diào)一次,所以我們可以通過(guò)設(shè)置動(dòng)畫(huà)時(shí)長(zhǎng)來(lái)控制監(jiān)聽(tīng)的頻率,比如上面是.3s的觸發(fā)頻率。
下面寫(xiě)了一個(gè)demo,可以實(shí)現(xiàn)自定義onresize事件
查看這個(gè)demo
小節(jié)以上通過(guò)借助css,實(shí)現(xiàn)了許多js都很棘手的問(wèn)題,可能還會(huì)有更多的應(yīng)用場(chǎng)景,歡迎小伙伴留言討論~
如果有新的想法,會(huì)第一時(shí)間更新在 https://github.com/XboxYan/no... ,多多關(guān)注
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104275.html
摘要:預(yù)讀取預(yù)讀取是一項(xiàng)使瀏覽器主動(dòng)去執(zhí)行域名解析的功能。在某些圖片較多的頁(yè)面中,在發(fā)起圖片加載請(qǐng)求之前預(yù)先把域名解析好將會(huì)有至少的圖片加載速度提升。但由于域名解析本身也是耗時(shí)的,所以也不是越多越好,最大支持路并發(fā),所以一般設(shè)置個(gè)域名較為合適。 文章本來(lái)是給公司內(nèi)部分享用的,現(xiàn)在發(fā)表出來(lái),歡迎大家提出寶貴建議。 背景目的 讓官網(wǎng)首頁(yè)加載速度更快,對(duì)用戶(hù)的操作響應(yīng)得更及時(shí),給用戶(hù)提供更為友好...
摘要:傳統(tǒng)的網(wǎng)頁(yè)編程采用的三劍客來(lái)實(shí)現(xiàn),在微信小程序中同樣有三劍客。觀(guān)察者模式不難實(shí)現(xiàn),重點(diǎn)是如何在微信小程序中搭配其特有的生命周期來(lái)使用。交互事件傳統(tǒng)的事件傳遞類(lèi)型有冒泡型與捕獲型,微信小程序中自然也有。 本文由作者鄒永勝授權(quán)網(wǎng)易云社區(qū)發(fā)布。 簡(jiǎn)介為了更好的展示我們即時(shí)通訊SDK強(qiáng)悍的能力,網(wǎng)易云信IM SDK微信小程序DEMO的開(kāi)發(fā)就提上了日程。用產(chǎn)品的話(huà)說(shuō)就是: 云信 IM 小程序 S...
摘要:非常的龐大,而且它是完全為設(shè)計(jì)而生的動(dòng)效庫(kù)。它運(yùn)行于純粹的之上,是目前最強(qiáng)健的動(dòng)畫(huà)資源庫(kù)之一。可能是創(chuàng)建滾動(dòng)特效最好用的工具,它支持大量的瀏覽器,只要它們支持和特性??梢酝ㄟ^(guò)安裝吊炸天了,接近現(xiàn)實(shí)生活中的物理運(yùn)動(dòng)碰撞慣性動(dòng)畫(huà)庫(kù)。 收集日期為2019-02-28,★代表當(dāng)時(shí)的該項(xiàng)目在github的star數(shù)量 Animate.css 56401 ★ 一個(gè)跨瀏覽器的動(dòng)效基礎(chǔ)庫(kù),是許多基礎(chǔ)動(dòng)...
摘要:還會(huì)有一個(gè)性能上的問(wèn)題就是當(dāng)頁(yè)面的列表過(guò)長(zhǎng),元素過(guò)多時(shí),在模擬滾動(dòng),下拉刷新這段時(shí)間內(nèi),頁(yè)面也會(huì)有卡頓現(xiàn)象,這里采取了一個(gè)優(yōu)化策略即列表較長(zhǎng)時(shí)數(shù)量較多時(shí),在觸發(fā)下拉刷新的時(shí)機(jī)時(shí)將頁(yè)面視窗之外的元素隱藏或者存放在里面。 移動(dòng)web滾動(dòng)問(wèn)題 在移動(dòng)端如果使用局部滾動(dòng),意思就是我們的滾動(dòng)在一個(gè)固定寬高的div內(nèi)觸發(fā),將該div設(shè)置成overflow:scroll/auto;來(lái)形成div內(nèi)部的...
閱讀 1255·2021-09-01 10:30
閱讀 2133·2021-07-23 10:38
閱讀 907·2019-08-29 15:06
閱讀 3161·2019-08-29 13:53
閱讀 3284·2019-08-26 11:54
閱讀 1837·2019-08-26 11:38
閱讀 2379·2019-08-26 10:29
閱讀 3134·2019-08-23 18:15