在任何場景下,公開的指出別人的 Bug 都不免會顯得情商有點過低。但相信掘金這樣優秀且開放的平臺是容得下不一樣聲音的,而且這個點我以爲值得和你們分享,因此多有得罪,還請見諒。瀏覽器
掘金首頁的列表出現了 <a/>
標籤的多級嵌套。雖然有在 JS 裏面處理父級跳轉的邏輯,但這個在個人認知裏好想是不太符合規範的。工具
好比咱們直接在 VSCode 裏面寫一個嵌套的 <a/>
,會發如今 Chrome 中這個嵌套的邏輯會被嘗試拍平成兩個同級的<a/>
標籤。3d
掘金首頁之因此依然保持了嵌套的邏輯,我猜想是由於主頁的列表是用 JS 動態渲染的,而後略過了瀏覽器的修復邏輯。code
只說別人不對,而不提出解決方案也是容易被打的。cdn
若是咱們去掉掘金首頁的列表的一些多餘的項,大概就會留下咱們上圖這樣的基礎結構。blog
這種數據列表是咱們網頁中很是常見的。一般爲了增長用戶體驗,雖然已經有點擊顯示更多的連接,從視覺上咱們仍然會讓整個 <li>
的點擊觸發點擊更多連接的邏輯。事件
因此添加一個包裹整個 <li/>
內部的元素的 <a/>
連接,是一個比較符合直覺的處理邏輯。由於總不可能用 JS 去監聽 <li/>
的點擊事件而後去觸發更多這個連接的跳轉吧?ci
我這邊能想到一個比較討巧的方案是這樣:it
讓咱們的 <a/>
直接絕對定位蓋在咱們整個 <li/>
區域,這樣咱們既不須要修改 DOM 結構,也不用經過 JS 去添加聯動事件,就能實現一樣的效果。io
固然這裏有兩個小問題須要注意:
z-index
就好。由於這裏我並無給更多連接設置 z-index
因此,我只須要讓後續元素設置 position:relative
就好。text-indent
負值來解決。可是這裏不推薦是用 opacity: 0;
來隱藏元素。由於 opacity
會一樣讓 <a/>
元素在 focus
狀態下的外發光消失。這個對於無障礙訪問不友好。對於這種建立空白遮罩的處理咱們姑且稱其爲幽靈遮罩。
幽靈遮罩 對於像上一節講到的拓展用戶可點擊區域,又或者你想讓用戶看到元素,但又不想要用戶能夠操做的相似場景是有奇效的。
這裏拿起點小說的閱讀頁舉例,我整個頁面想要點擊除開書封和黃色區域之外的區域都觸發工具欄。
若是用 JS 去判斷,就要監聽整個頁面的點擊事件,而後判斷這個點擊事件是否冒泡到書封或者是黃色區域。若是是則阻止這個點擊事件,若是不是則呼出工具欄。而且若是這個頁面後續的按鈕增長,這邊的 JS 邏輯就會隨着增長,會有一種費力不討好的感受。
而此時若是採用 幽靈遮罩 的方案。很簡單,你只須要建立一個幽靈遮罩, 將呼出工具欄的事件綁定到 幽靈遮罩 上。對於有其它點擊邏輯的元素,只須要將其 z-index
設定到超過 幽靈遮罩 的地方搞定。全局就一個JS 綁定事件,哪有啥冒泡不冒泡的邏輯。後續拓展也是隻須要設置 z-index
簡單又方便。
再好比,你有一個複雜的表單,你在點擊了 submit 按鈕,而後數據正在發送的過程當中。你不想讓用戶操做其它的控件,或者屢次點擊 submit。你只須要在用戶點擊 submit 的時候,讓這個 幽靈遮罩 出現,loading 完成以後讓 幽靈遮罩 消失。
這樣用戶全部在 loading 狀態下的點擊都會被 幽靈遮罩 攔截,你甚至能夠直接在用戶點擊 幽靈遮罩 的以後,彈出一個 toast 告訴用戶當前正在 loading 當中。而這整個邏輯若是不用 幽靈遮罩 實現實際上是滿複雜的。
而且這整個過程用戶是無感知的。由於,之因此叫 幽靈遮罩 就是用戶看不到的遮罩。
講到 幽靈遮罩 又不得不提一個與之相似的屬性 pointer-events: none;
。
pointer-events: none;
是讓用戶看到,可是碰不到;這個屬性也一樣適用於,你不想讓 submit 按鈕被用戶屢次點擊觸發屢次submit的邏輯。只須要在用戶點擊了按鈕以後,裏面給按鈕設定一個 pointer-events: none;
屬性,在好比說 loading 完或者 500ms 以後再去掉這個屬性。這樣就能很方便的作到點擊截流。
整個邏輯都屬於我的經驗之談,有不正確的歡迎指正。
也歡迎你們分享使用 幽靈遮罩 解決棘手問題的相似場景。