jquery 新建元素的事件綁定

我想不少人都會向我同樣曾經被動態添加元素的事件綁定困惑好久,也就是在頁面加載完成後給已有元素綁定了事件,但又新增長的元素上卻沒有綁定任何事件。 css

js的事件監聽跟css不同,css只要設定好了樣式,不管是原來就有的仍是新添加的,都有同樣的表現。而事件監聽不是,你必須給每個元素單獨綁定事件。 html

常見的例子是處理表格的時候。每行行末有個刪除按鈕,點了這個可以刪除這一行。 app

< table >
    
< tbody >
        
< tr >
            
< td > 這行原來就有 </ td >
            
< td >< button class = " del " > 刪除 </ button ></ td >
        
</ tr >
        
< tr >
            
< td > 這行原來就有 </ td >
            
< td >< button class = " del " > 刪除 </ button ></ td >
        
</ tr >
    
</ tbody >
</ table >

一般,我會這麼綁定 dom

  1. jQuery(function($){
  2.    //已有刪除按鈕初始化綁定刪除事件
  3.     $(".del").click(function() {
  4.         $(this).parents("tr").remove();
  5.    });
  6. });

對於在domready以前就存在的刪除按鈕,一切都很完美。但若是在domready以後用js動態添加幾行,那新增的幾行中的這些按鈕都將失去任何做用。 函數

如何解決這個問題?如下提供4種解決方案:
=============================
0號解決方案——onclick法
若是不顧結構與行爲分離的準則的話,一般,我會這麼作。
注意,此時的deltr這個function必須是全局函數,得放jQuery(function($) {})外面,放裏邊就成局部函數了,html裏的onclick就調用不到了! 測試

  1. <td><buttononclick="deltr(this)">刪除</button></td>
  1. jQuery(function($){
  2.    //添加行
  3.     $("#add2").click(function(){
  4.         $("#table2>tbody").append('<tr><td>新增行</td><td><button nclick="deltr(this)">刪除</button></td></tr>')
  5.    });
  6. });
  7. //刪除行的函數,必需要放domready函數外面
  8. function deltr(delbtn){
  9.     $(delbtn).parents("tr").remove();
  10. };

=============================
1號解決方案——重複綁定法
即,在domready的時候就給已有的元素綁定事件處理函數,
然後當新增長的元素的時候再次綁定。 this

  1. <td><buttonclass="del">刪除</button></td>
  1. jQuery(function($){
  2.    //定義刪除按鈕事件綁定
  3.    //寫裏邊,防止污染全局命名空間
  4.    function deltr(){
  5.         $(this).parents("tr").remove();
  6.    };
  7.    //已有刪除按鈕初始化綁定刪除事件
  8.     $("#table3 .del").click(deltr);
  9.    //添加行
  10.     $("#add3").click(function(){
  11.         $('<tr><td>新增行</td><td><button class="del">刪除</button></td></tr>')
  12.            //在這裏給刪除按鈕再次綁定事件。
  13.             .find(".del").click(deltr).end()
  14.             .appendTo($("#table3>tbody"));
  15.    });
  16. });

=============================
2號解決方案——事件冒泡法
利用事件冒泡的原理,咱們給這個按鈕的祖先元素綁定事件處理函數。
而後經過event.target這個對象來判斷,這個事件是否是咱們要找的對象觸發的。
一般能夠利用一些DOM屬性,好比event.target.className、event.target.tagName等之類的來判斷。 spa

  1. <td><buttonclass="del">刪除</button></td>
  1. jQuery(function($){
  2.    //第四個表格的刪除按鈕事件綁定
  3.     $("#table4").click(function(e) {
  4.        if (e.target.className=="del"){
  5.             $(e.target).parents("tr").remove();
  6.        };
  7.    });
  8.    //第四個表格的添加按鈕事件綁定
  9.     $("#add4").click(function(){
  10.         $("#table4>tbody").append('<tr><td>新增行</td><td><button class="del">刪除</button></td></tr>')
  11.    });
  12. });
3號解決方案——複製事件法
上面幾種方案能夠說即使你沒有用到jQuery庫,你也能相對比較容易的實現。但這種方案相對依賴jQuery的程度更高。並且必需要求jQuery 1.2版以上。低版本jQuery須要插件。
上面兩個方案都是對刪除函數動了不少腦筋,換了多種觸發、綁定的方式。這個方案不一樣,能夠與平時純靜態的元素同樣在domready的時候綁定。但在咱們添加新行的時候咱們改動一下,再也不想上面那樣拼接字符串來添加新行了。這回咱們嘗試使用複製DOM元素的方式。而且複製的時候連同綁定的事件一塊兒複製,複製完以後再用find之類的修改內部的元素。
同時,就像這個例子,若是你會把全部元素都刪除光,那template這個模板是必須的,若是不會刪光,那就未必須要用template了。爲了防止被誤刪,此處我把template設了隱藏。
我使用了jQuery中特有的clone(true)
  1. .template{display:none;}
  1. <trclass="template">
  2.            <td>這裏是模板</td>
  3.            <td><button class="del">刪除</button></td>
  4.        </tr>
  5.        <tr>
  6.            <td>這行原來就有</td>
  7.            <td><button class="del">刪除</button></td>
  8.        </tr>
  9.        <tr>
  10.            <td>這行原來就有</td>
  11.            <td><button class="del">刪除</button></td>
  12.        </tr>
  1. jQuery(function($){
  2.    //第五個表格的刪除按鈕事件綁定
  3.     $("#table5 .del").click(function() {
  4.         $(this).parents("tr").remove();
  5.    });
  6.    //第五個表格的添加按鈕事件綁定
  7.     $("#add5").click(function(){
  8.         $("#table5>tbody>tr:eq(0)")
  9.            //連同事件一塊兒複製
  10.             .clone(true)
  11.            //去除模板標記
  12.             .removeClass("template")
  13.            //修改內部元素
  14.             .find("td:eq(0)")
  15.                 .text("新增行")
  16.                 .end()
  17.            //插入表格
  18.             .appendTo($("#table5>tbody"))
  19.    });
  20. });

=============================
總評:
上面4種方案,各有優劣。
0號方案,結構與行爲徹底沒有分離,並且污染全局命名空間。最不推薦。因此我都不把它看成一個方案來看。但對於js初學者,能夠用來項目救急。
1號方案,中規中矩,沒啥好也沒啥很差
2號方案,這種方法充分的發揮了js事件冒泡的優點。並且效率最高。但同時因爲這種方案無視了jQuery強大的選擇器,因此若是涉及的元素屬性要求過多就會比較麻煩了。你會徘徊在衆多if的條件的是非關係之中。後來我想起來,能夠用jQuery中的$(event.target).is(selector)來做爲條件。這樣能夠極大提高開發效率,但略微下降執行效率。
3號方案,這是我認爲最能體現結構與行爲分離的思想的一種方案。但缺點也很明顯,對於jQuery依賴性過於高了,要不就本身寫一個複製連同事件一塊兒複製的函數,但這也顯然對於初學者來講異常困難。但從將來的趨勢的角度來看,仍是很推薦使用這種方案的。 插件

具體選用哪個方案,沒有定數。具體看你的項目以及你js還有結構與行爲分離的思想的掌握程度。最適合的纔是最好的。 code

=============================
附加:
把3號方案改形成完美的結構行爲分離的樣式。
首先,帶有template的是模板元素。他是一切複製的源泉,爲了防止被誤刪,因此設爲不可見。若是不會刪除光,那麼這個模板元素也是可選的。由於你能夠複製任何一個已經存在的用於循環元素。
其次,給每一個重複的元素加上一個repeat,方便用於刪除按鈕找到這一級元素。這個是可選的,有時候並不須要。
最後是給每個要修改的元素加上一個類,便於用find找到。好比我這裏就家了content類,新增長的能夠修改裏邊的值。
這樣一個完美的結構與行爲分離的案例就完成了。

  1. <tableid="table6">
  2.    <tbody id="tbody6">
  3.        <tr class="template repeat">
  4.            <td class="content">這裏是模板</td>
  5.            <td><button class="del">刪除</button></td>
  6.        </tr>
  7.        <tr class="repeat">
  8.            <td class="content">這行原來就有</td>
  9.            <td><button class="del">刪除</button></td>
  10.        </tr>
  11.        <tr class="repeat">
  12.            <td class="content">這行原來就有</td>
  13.            <td><button class="del">刪除</button></td>
  14.        </tr>
  15.    </tbody>
  16.    <tfoot>
  17.        <tr>
  18.            <td>&nbsp;</td>
  19.            <td><button id="add6">添加</button></td>
  20.        </tr>
  21.    </tfoot>
  22. </table>
  1. jQuery(function($){
  2.    //第六個表格的刪除按鈕事件綁定
  3.     $("#tbody6 .del").click(function() {
  4.         $(this).parents(".repeat").remove();
  5.    });
  6.    //第六個表格的添加按鈕事件綁定
  7.     $("#add6").click(function(){
  8.         $("#tbody6>.template")
  9.            //連同事件一塊兒複製
  10.             .clone(true)
  11.            //去除模板標記
  12.             .removeClass("template")
  13.            //修改內部元素
  14.             .find(".content")
  15.                 .text("新增行")
  16.                 .end()
  17.            //插入表格
  18.             .appendTo($("#tbody6"))
  19.    });
  20. });

一樣,這段js也適用於以下的html結構

  1. <ulid="tbody6">
  2.    <li class="template repeat">
  3.        <span class="content">這裏是模板</span>
  4.        <span><button class="del">刪除</button></span>
  5.    </li>
  6.    <li class="repeat">
  7.        <span class="content">這行原來就有</span>
  8.        <span><button class="del">刪除</button></span>
  9.    </li>
  10.    <li class="repeat">
  11.        <span class="content">這行原來就有</span>
  12.        <span><button class="del">刪除</button></span>
  13.    </li>
  14. </ul>

其餘動態綁定事件的方法:

$("#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()
相關文章
相關標籤/搜索