iOS下瀏覽器document/body的click事件無效的坑

簡離發表於2019-02-01

最近要在一個移動端頁面上新增一個下拉選單,點選下拉,然後點選頁面任何位置列表收回,這個功能很簡單,在PC端也實現過很多次,基本思路就是在document/body上繫結click事件,觸發時隱藏下拉選單。

開發時一切正常,在Chrome的模擬手機瀏覽器上測試也一切正常,但是在iOS下的Safari上測試,列表可以展開,在頁面任意位置點選收回的功能卻失效了。

Chrome模擬手機瀏覽器上一切正常,真機卻有問題,在網上搜尋的除錯方法基本上都需要Mac(流下了貧窮的眼淚),只能一點一點修改js來除錯了。

首先的思路就是排除其他變數,我在一個測試頁面上實現了相同的下拉表單,並在document/body上繫結了click事件,然後發現一切正常。

iOS下瀏覽器document/body的click事件無效的坑
這就更尷尬了,難道是其他部分js的影響嗎,檢查之後發現沒有其它document/body相關的操作(此處消耗了大量的時間,並且是無用功),只能面向谷歌/百度程式設計了,網上的建議如下:

  • 將 click 事件委託到非documentbody的父級元素上。
    這是有效的,如果將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事件無效的坑
對著兩個頁面苦思冥想了半個小時,突然靈光一閃:頁面長度不一樣!!!我試著在測試功能頁面加了一堆br將頁面撐開到超過一屏,然後測試功能頁面就出現同樣的問題啦。

所以推論如下,iOS下的瀏覽器,觸發document/body的click事件時,如果頁面超過一屏,會認為這是網頁雙擊向下翻頁的第一次點選,這屬於瀏覽器的預設行為,我們自己定義的click事件就失效了。但是如果頁面都沒有超過一屏,這個翻頁的預設行為不存在,我們自己定義的click事件就可以執行了,大功告成~

iOS下瀏覽器document/body的click事件無效的坑

相關文章