最近要在一個移動端頁面上新增一個下拉選單,點選下拉,然後點選頁面任何位置列表收回,這個功能很簡單,在PC端也實現過很多次,基本思路就是在document/body上繫結click事件,觸發時隱藏下拉選單。
開發時一切正常,在Chrome的模擬手機瀏覽器上測試也一切正常,但是在iOS下的Safari上測試,列表可以展開,在頁面任意位置點選收回的功能卻失效了。
Chrome模擬手機瀏覽器上一切正常,真機卻有問題,在網上搜尋的除錯方法基本上都需要Mac(流下了貧窮的眼淚),只能一點一點修改js來除錯了。
首先的思路就是排除其他變數,我在一個測試頁面上實現了相同的下拉表單,並在document/body上繫結了click事件,然後發現一切正常。
![iOS下瀏覽器document/body的click事件無效的坑](https://i.iter01.com/images/61a84f3039e3658029260c6cea6cd5450685b42b6a8012fea3b37060e253c085.jpg)
- 將 click 事件委託到非
document
或body
的父級元素上。
這是有效的,如果將body與body內的全部元素之間加一層div,然後將之前繫結到document或者body的事件繫結在此div上,功能就正常了。 - 給目標元素加一條樣式規則
cursor: pointer
。
首先無法給document上加樣式規則,但是給body加此樣式規則的話,功能就正常了,原因是iOS的瀏覽器下的document和body在加上cursor: pointer
這個樣式規則後,被認為是可點選元素,也就可以觸發click事件了。
網上說只有a和btn被認為是可點選元素,經過測試,只有document和body是特殊元素,需要加cursor: pointer
才可以觸發click事件,其他元素均可以正常觸發click事件。 - 繫結touchstart事件。
這個也是有效的,在移動端touchstart事件總是可以被觸發的,所以可以將click事件替換為touchstart事件。如果需要做響應式頁面,針對PC端和移動端同時優化的話,比如在jQuery下,可以使用$(document).on('click touchstart', function() {// do something...})
。
其實問題到這裡就解決了(如果就這麼解決我也不會寫這篇文章了-_-||),但是總有個問題在我心頭揮之不去,為什麼之前我的測試功能頁面只在document繫結click就一切正常,正式頁面卻不行呢,兩個頁面明明沒什麼區別,這個問題不解決怎麼能算是學到東西了呢。
![iOS下瀏覽器document/body的click事件無效的坑](https://i.iter01.com/images/e0c7aba5d5ad2379ca27a47b0c8c48dc8a82c42e4a946fbf528f930b1b97cb80.jpg)
所以推論如下,iOS下的瀏覽器,觸發document/body的click事件時,如果頁面超過一屏,會認為這是網頁雙擊向下翻頁的第一次點選,這屬於瀏覽器的預設行為,我們自己定義的click事件就失效了。但是如果頁面都沒有超過一屏,這個翻頁的預設行為不存在,我們自己定義的click事件就可以執行了,大功告成~
![iOS下瀏覽器document/body的click事件無效的坑](https://i.iter01.com/images/b41d10ac9b31fbbd9df498a3880785058618be7ee8e4ecf22f583d85c36ea1b9.jpg)