因爲實際的須要,有時須要往網頁中動態的插入HTML內容,並在插入的節點中綁定事件處理函數。咱們知道,用Javascript向HTML文檔中 插入內容,有兩種方法,javascript
一種是在寫HTML代碼寫入JS,而後插入到文檔中;html
另一種是經過ajax的方式,從服務器獲取數據,而後用js把獲取的數據經 過處理後插入文檔中;java
兩種方法各有特色,本文將分析新插入到文檔中的元素的事件綁定問題,並假定新插入的對象不作內聯的事件綁定(即不用相似 <a onclick=」」>的形式)。全部的示例將會用到jQuery和原生Javascript。
node
狀況一: HTML代碼存放在JS中,請看如下代碼:
<body> <p>第1行內容</p> <p>第2行內容</p> <p>第3行內容</p> <script> var appendhtml=document.createElement("p"); appendhtml.innerHTML="這是插入的內容"; document.body.appendChild(appendhtml); var nodep=document.getElementsByTagName("p"); for (var i=0;i<nodep.length;i++){ nodep[i].onclick=function(){ console.log("Click Event!"); } } </script> </body>
上面的代碼是用原生的Javascript生成的,當此代碼執行時,js會在頁面中生成第四個P標籤,且點擊這四個標籤的時候,都會觸發相應的動 做。那麼是否是就是說,用js生成的HTML內容,均可以被綁定相應的事件呢?答案是否認的,在上面代碼的script標籤中,有兩個代碼段,代碼段一是 用來向HTML中插入內容的,代碼段二是用來綁定事件的,若是把代碼段一和代碼段二互換位置,發現JS生成的第四個P標籤沒有綁定上click事件。用以 下代碼的jquery測試:jquery
$(function(){ $("p").click(function(){ console.log("Click Event"); }) $("<p>這是生成的內容</p>").appendTo("body"); })
發現結果也同樣,事件執行成功與否也代碼段的順序有直接的關係。其實原來很好分析,不管是利用getElementsByTagName仍是jquery的選擇器,當須要的內容尚未被插入時,選擇器只會選擇頁面中已經存在的元素,因此事先沒有存在元素是綁定不了事件的。ajax
可是,實際狀況是,工做中有可能須要把後來生成的元素綁定上事件,並註冊上事件處理函數。例如本網站的留言系統,第一次加載只會顯示固定條數的評 論,若是評論超過必定數量,剩下的會用ajax的方式進行加載。全部的留言最後都有個回覆功能,點擊能夠恢復相應的留言,也就是說,動態加載上來的留言, 也許要綁定click事件,並註冊上回復留言的函數。固然偷懶的方法是,爲ajax加載上來的內容再註冊一個click並再綁定一次相應的函數,但這加大 了代碼的冗餘度,增長系統開銷,還會使代碼變得難以理解。那麼更好的解決辦法是什麼呢?api
能夠這樣理解,不管HTML內容是否是JS生成的,只要沒有跨域,全部頁面內的元素都屬於這個頁面,都可以綁定事件,JS中有個很是重要的概念叫事件冒泡,簡單來說,就是子元素產生的事件,會一直冒泡到最頂級父元素,並可以被父元素監測到。請看下圖:服務器
那麼,我能不能在被插入元素的父元素上監測冒泡產生的事件,並回調相應的函數呢?答案是固然是確定的。來看下面的例子,注意網頁面裏插入內容是在JS代碼的最後。
<script> $(function(){ $("body").delegate("p","click",function(){ console.log("Click Event"); }) $("<p>這是生成的內容</p>").appendTo("body"); }) </script>
這是,發現全部的P元素點擊都產生了輸出,說明代碼運行成功。這裏咱們用到了jQuery的delegate函數,來看一下官方解釋:
Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.
根據特定的根元素,把一個或者多個事件註冊到指定的元素上,不論這個元素如今是否存在。
在jQuery1.7.3以上的版本中,on方法也能夠作這件事,官方有示例說明,這裏再也不贅述。
好比有一些狀況屢次從後臺獲取動態內容到前臺,點擊的時候會觸發屢次,還要使用 $("body").undelegate(); 解除以前的綁定 而後再一次從新綁定。
$("body").undelegate(); $("body").delegate(".reply_check_btn", "click", function () { alert('adsadsa'); });