我想不少人都會向我同樣曾經被動態添加元素的事件綁定困惑好久,也就是在頁面加載完成後給已有元素綁定了事件,但又新增長的元素上卻沒有綁定任何事件。 css
js的事件監聽跟css不同,css只要設定好了樣式,不管是原來就有的仍是新添加的,都有同樣的表現。而事件監聽不是,你必須給每個元素單獨綁定事件。 html
常見的例子是處理表格的時候。每行行末有個刪除按鈕,點了這個可以刪除這一行。 app
一般,我會這麼綁定 dom
對於在domready以前就存在的刪除按鈕,一切都很完美。但若是在domready以後用js動態添加幾行,那新增的幾行中的這些按鈕都將失去任何做用。 函數
如何解決這個問題?如下提供4種解決方案:
=============================
0號解決方案——onclick法
若是不顧結構與行爲分離的準則的話,一般,我會這麼作。
注意,此時的deltr這個function必須是全局函數,得放jQuery(function($) {})外面,放裏邊就成局部函數了,html裏的onclick就調用不到了! 測試
=============================
1號解決方案——重複綁定法
即,在domready的時候就給已有的元素綁定事件處理函數,
然後當新增長的元素的時候再次綁定。 this
=============================
2號解決方案——事件冒泡法
利用事件冒泡的原理,咱們給這個按鈕的祖先元素綁定事件處理函數。
而後經過event.target這個對象來判斷,這個事件是否是咱們要找的對象觸發的。
一般能夠利用一些DOM屬性,好比event.target.className、event.target.tagName等之類的來判斷。 spa
=============================
總評:
上面4種方案,各有優劣。
0號方案,結構與行爲徹底沒有分離,並且污染全局命名空間。最不推薦。因此我都不把它看成一個方案來看。但對於js初學者,能夠用來項目救急。
1號方案,中規中矩,沒啥好也沒啥很差
2號方案,這種方法充分的發揮了js事件冒泡的優點。並且效率最高。但同時因爲這種方案無視了jQuery強大的選擇器,因此若是涉及的元素屬性要求過多就會比較麻煩了。你會徘徊在衆多if的條件的是非關係之中。後來我想起來,能夠用jQuery中的$(event.target).is(selector)來做爲條件。這樣能夠極大提高開發效率,但略微下降執行效率。
3號方案,這是我認爲最能體現結構與行爲分離的思想的一種方案。但缺點也很明顯,對於jQuery依賴性過於高了,要不就本身寫一個複製連同事件一塊兒複製的函數,但這也顯然對於初學者來講異常困難。但從將來的趨勢的角度來看,仍是很推薦使用這種方案的。 插件
具體選用哪個方案,沒有定數。具體看你的項目以及你js還有結構與行爲分離的思想的掌握程度。最適合的纔是最好的。 code
=============================
附加:
把3號方案改形成完美的結構行爲分離的樣式。
首先,帶有template的是模板元素。他是一切複製的源泉,爲了防止被誤刪,因此設爲不可見。若是不會刪除光,那麼這個模板元素也是可選的。由於你能夠複製任何一個已經存在的用於循環元素。
其次,給每一個重複的元素加上一個repeat,方便用於刪除按鈕找到這一級元素。這個是可選的,有時候並不須要。
最後是給每個要修改的元素加上一個類,便於用find找到。好比我這裏就家了content類,新增長的能夠修改裏邊的值。
這樣一個完美的結構與行爲分離的案例就完成了。
一樣,這段js也適用於以下的html結構
其餘動態綁定事件的方法:
$("#table").on('click', 'button.del', function(e) {
alert('綁定事件了');
});//做用:測試在動態添加的<tr>上設置一個刪除按鈕的可行性,"test"是button的一個class,"#table"是table的id.
on(events,[selector],[data],fn) events:一個或多個用空格分隔的事件類型和可選的命名空間,如"click"或"keydown.myPlugin" 。 selector:一個選擇器字符串用於過濾器的觸發事件的選擇器元素的後代。若是選擇器爲null或省略,當它到達選定的元素,事件老是觸發。 data:當一個事件被觸發時要傳遞event.data給事件處理函數。 fn:該事件被觸發時執行的函數。 false 值也能夠作一個函數的簡寫,返回false。 替換bind() 當第二個參數'selector'爲null時,on()和bind()其實在用法上基本上沒有任何區別了,因此咱們能夠認爲on()只是比bind()多了一個可選的'selector'參數,因此on()能夠很是方便的換掉bind()