作前端最難受的就是產品給的需求以及測試給的bug了,看待這個標題是否是有點蒙,這是什麼需求,下面來解讀下!
需求:以下圖,點擊已保存按鈕彈出已保存列表,當點擊屏幕其餘區域要關閉這個下拉框,是否是很簡單前端
加點東西,可是點擊這個下拉框內部的區域不能關閉下拉框)(原諒我裏面沒寫東西你就當有東西,給個機會噻!),是否是很常見,是否是很噁心!大家是怎麼作的。 以前我見過有人把事件掛在window
上,而後把不想要操做dom
都掛上class
,而後在點擊事件裏面一一排除括弧笑,或者有人投機取巧在一部分dom上掛了事件,結果又是測試不是每次都能關閉,全看運氣!react
接天就來講下個人解決辦法,由於我是寫的react,我就直接上react代碼了,邏輯都是同樣,無妨!數組
首先在componentDidMount
中寫下咱們函數的觸發:dom
window.addEventListener('click', (event) => { event = event || window.event; this.setState({ savedListShow: false, // 這個是控制列表顯隱的狀態 }); })
事件掛在window上怎麼避免點擊列表內部的dom不會觸發呢,不要說什麼阻止冒泡,很差使的,首先咱們在事件中輸出咱們event,
看看究竟是什麼!函數
這是我點擊列表內部輸出的event。測試
說是路徑,其實在深一步輸出出來的是js對象
,既然是js對象那咱們就能拿到對象上的calss屬性了,對於咱們的判斷也就不成問題了。this
去代碼中到找咱們不想要觸發的那個(或者是一堆)不想觸發的dom的最大父級,spa
對的我這裏是class爲SavedList
的div,在最前邊(記住是最前邊)加上一個class _&saveBtn
(別人不用的,省得衝突)。code
在細看下上邊我點擊輸出的event中的path, 每個元素.
後的就是class, 注意橫線處的class,這說明我點擊的事件源是我不但願觸發的區域,而後咱們回到最開始componentDidMount
中的事件函數。component
componentDidMount() { // 點擊其餘區域關閉已保存條件彈窗 window.addEventListener('click', (event) => { event = event || window.event; let isSaveStructure = event.path.some(item => { 這裏使用了startsWith,相對來講比較嚴謹,這要是爲何強調要在最前邊添加的緣由了 if (item.className && item.className.startsWith('_&saveBtn')) { return true; } }); if (!isSaveStructure) { this.setState({ savedListShow: false }); } }) }
這樣依賴咱們不想觸發的dom以及dom內部的元素,遇到這個點擊事件就會唄排除在外了,是否是很省心。
window.addEventListener('click', (event) => {})
;class
,好比class
爲SavedList
的div以及內部dom不須要觸發那就在SavedList
上添加須要識別的class
, 主要要避免和其餘人的衝突,最好是特殊一點;path
裏面的是一個數組,包含的是js對象
,抓取返回回來的className
是string
類型,不是數組,咱們判斷使用的是startsWith();