[jQuery] 動態建立元素的事件觸發

我們有個舊專案使用早期的jQuery 1.2,剛巧新增功能的動態建立新元素讓原有的事件無法被觸發,測試後才知道「既有元素」的事件程式無法套用給「未來動態建立的元素」,在jQuery 1.7後使用 .on() 就能有效處理既有與未來元素的事件操作了。

▼ 測試網頁
test page

靜態 tr 元素一切正常

表格 TABLE1 原本有5個靜態的 tr,點擊換背景色與刪除、修改等皆能正常運作。但按下〔Add〕動態新增的 tr 完全無法觸發這些 click 事件。

<html>
<head>
  <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
  <style>
    .highlight {
      color: white;
      background-color: highlight;
    }
  </style>
</head>
<body>
<input type="button" id="btnAdd" value=" Add "> <span id="SPAN1"></span>
<table id="TABLE1" border="1">
  <tbody id="TBODY1">
    <tr class='row'><td>static text 1</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>
    <tr class='row'><td>static text 2</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>
    <tr class='row'><td>static text 3</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>
    <tr class='row'><td>static text 4</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>
    <tr class='row'><td>static text 5</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>
  </tbody>
</table>
</body>
</html>

<script>
  var iCurrentRowIndex_ = -1;
  
  $(document).ready(function() {
    $("#btnAdd").click(function() {
      $("#TBODY1").append("<tr class='row'><td>" + (new Date()) + 
        "</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>");
    });
    
    $(".row").click(function() {
      if (iCurrentRowIndex_ > -1) {
        $('.row:nth-child(' + (iCurrentRowIndex_+1) +')').removeClass('highlight');
      }
      
      $(this).addClass('highlight');
      iCurrentRowIndex_ = $(this).index();
    });
    
    
    $(".delButton").click(function() {
      $(this).parent().parent().remove();
    });
    

    $(".editButton").click(function() {
      var tr = $(this).parent().parent();
      var _sText = tr.find("td").eq(0).text();  // get the 1st cell's innerText
      $("#SPAN1").text(" Edit: " + _sText);
    });
    
  });
</script>

動態建立的新元素

只要把 click 事件改寫成 .delegate() 或 .on() 才能解決這個問題。範例直接使用 .on()和.delegate() 來撰寫。.on()的使用語法是:

selector.on( events [, sub-selector ] [, data ], handler )

例如:

$("table tr").on("click", "td:nth-child(1)", function() {
  // some code...
});

修改後的程式碼如下:

<html>
<head>
  <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
  <style>
    .highlight {
      color: white;
      background-color: highlight;
    }
  </style>
</head>
<body>
<!--
http://jsfiddle.net/emisjerry/53v4o3ha/
-->
<input type="button" id="btnAdd" value=" Add "> <span id="SPAN1"></span>
<table id="TABLE1" border="1">
  <tbody id="TBODY1">
    <tr class='row'><td>static text 1</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>
    <tr class='row'><td>static text 2</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>
    <tr class='row'><td>static text 3</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>
    <tr class='row'><td>static text 4</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>
    <tr class='row'><td>static text 5</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>
  </tbody>
</table>
</body>
</html>

<script>
  var iCurrentRowIndex_ = -1;
  
  $(document).ready(function() {
    $("#btnAdd").click(function() {
      $("#TBODY1").append("<tr class='row'><td>" + (new Date()) + 
        "</td><td><input type='Button' value='Delete' class='delButton'><input type='Button' value='Edit' class='editButton'></td></tr>");
    });
    
    /*$(".row").click(function() {
      if (iCurrentRowIndex_ > -1) {
        $('.row:nth-child(' + (iCurrentRowIndex_+1) +')').removeClass('highlight');
      }
      
      $(this).addClass('highlight');
      iCurrentRowIndex_ = $(this).index();
    });*/
    
    $("#TBODY1").on("click", ".row", function() {
      if (iCurrentRowIndex_ > -1) {
        $('.row:nth-child(' + (iCurrentRowIndex_+1) +')').removeClass('highlight');
      }
      
      $(this).addClass('highlight');
      iCurrentRowIndex_ = $(this).index();
    });
    
    /*$(".delButton").click(function() {
      $(this).parent().parent().remove();
    });*/
    
    $("#TBODY1").delegate(".delButton", "click", function() {
      $(this).parent().parent().remove();  // $(this) is #TBODY1
    });

    /*$(".editButton").click(function() {
      var tr = $(this).parent().parent();
      var _sText = tr.find("td").eq(0).text();  // get the 1st cell's innerText
      $("#SPAN1").text(" Edit: " + _sText);
    });*/
    
    $("#TBODY1").delegate(".editButton", "click", function() {
      var tr = $(this).parent().parent();
      var _sText = tr.find("td").eq(0).text();  // get the 1st cell's innerText
      $("#SPAN1").text(" Edit: " + _sText);
    });
   
  });
</script>

測試檔案下載或執行

點擊執行或按右鍵另存新檔。

##

您可能也會有興趣的類似文章

簡睿

服務於軟體業的資訊老兵。興趣廣泛,學習力佳,樂於分享所知所學。

您可能也會喜歡…

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *