最近同事問到一個問題,一個前端頁面在IOS端真機測試下出現一個比較詭異的問題,若是沒有遇到過估計也是束手無策。今天特此記錄一下,或許能幫到後面遇到這個問題的朋友少繞一些彎路。這是關於JQuery 中的 delegate 和 on 給動態元素綁定事件觸發不了的問題。文章如下只用 delegate 舉例。css
首先咱們來了解一下 Delegate 的做用。一句話帶過:「給動態添加的元素綁定事件」html
看圖:前端
下面九個測試按鈕是經過點擊上面的 「添加測試按鈕」 按鈕添加的。這就是動態添加元素的概念。接下來需求爲每一個添加的測試按鈕都有統一的處理事件。這邊做爲測試,當點擊時輸出 「你點擊了+按鈕名稱」 信息。 按平時綁定事件的方式,.click() 或者 on('click') 等等這些方式。代碼以下jquery
$(function(){ //「添加測試按鈕」 按鈕點擊事件,測試按鈕 class 爲 new-btn $("#add-btn").click(function(){ var test_btn_count = $('#btn-line button').size(); var new_btn_html = '<div class="new-btn btn">測試按鈕' + (test_btn_count + 1) +'</div>'; $('#btn-line').append(new_btn_html); }); //用普通的click 綁定事件。很遺憾,沒任何反應 $('.new-btn').click(function(){ console.log('你點擊了按鈕:'+$(this).text()); }) })
效果如圖:web
接下來咱們將普通的綁定事件換成 delegate ,代碼以下:canvas
//btn-line 爲存放 new-btn 的容器 $('.btn-line').delegate('.new-btn','click',function(){ console.log('你點擊了按鈕:'+$(this).text()); })
delegate 效果ruby
至此,Delegate 解決了動態元素的事件綁定問題。app
上面好像已經實現了咱們要的需求,但事實證實真正的坑還在後面。如今 Chrome 下面的 IOS模擬器下面所有正常。可是當項目正在跑在真機上,點擊測試按鈕又失去了反應。爲了在手機上看到效果,咱們先把 console.log 換成 alertide
$('.btn-line').delegate('.new-btn','click',function(){ alert('你點擊了按鈕:'+$(this).text()); })
結果是界面直接懵圈了。post
點擊沒有任何的 alert 信息
針對這個問題開始了搜索之旅,功夫不負有心人(其實不難搜到)。一切詭異的問題後面都會有一個神奇的解決方案。
給動態添加的 new-btn 添加 css cursor屬性
.new-btn{ cursor: none; }
神奇地好了
網友對此的回答以下:
其實蘋果對於性能的要求是近乎苛刻的,這樣的特性應該是蘋果爲了節省性能開銷而產生的一個bug。若是沒有可點的特性的元素系統默認不會給它響應事件。而咱們添加的這個 cursor 屬性就是讓元素看起來是能夠點擊的,也就向操做系統指明這個元素是須要響應事件的。
也就是說,想要一勞永逸,給body 添加 cursor:pointer 樣式屬性。或者按照網友提供的方法,經過js判斷當前是否爲蘋果設備,若是是則加上。
代碼以下:
if(/ip(hone|od)|ipad/i.test(navigator.userAgent)){ $("body").css("cursor","pointer"); }
其實我到時以爲css代碼更乾脆
body{ cursor:none;
/*cursor:pointer;*/
}
//或者 *{ cursor:pointer; }
可是直接給body或者是給 * 添加這個屬性都違背了蘋果節約性能開銷的初衷,最好的方式仍是直接給須要響應事件的元素添加 cursor 屬性.
.yourElementClass{
cursor:pointer;
}
限於筆者技術,文章觀點不免有不當之處,但願發現問題的朋友幫忙指正,筆者將會及時更新。也請轉載的朋友註明文章出處並附上原文連接,以便讀者能及時獲取到文章更新後的內容,以避免誤導讀者。筆者力求避免寫些晦澀難懂的文章(雖然也有人說這樣顯得高逼格,專業),儘可能使用簡單的用詞和例子來幫助理解。若是表達上有好的建議的話也但願朋友們在評論處指出。
本文爲做者原創,轉載請註明出處! Cboyce