2011-08-09 30 views
7

Tôi có một tình huống mà tại một thời điểm nội dung html của một div được thay đổi thành cái gì khác, và sau đó được thay đổi trở lại. Một số điều khiển jquery ui là không đúng. Tôi đã giảm vấn đề xuống đoạn mã sau, về cơ bản cho thấy trình xử lý sự kiện được liên kết với nút không kích hoạt nữa. Tôi giả định rằng đây là rác được thu thập tại một số thời điểm khi họ đã đi. Vì vậy, câu hỏi của tôi là -javascript sự kiện bị thiếu sau khi đặt lại html

Làm cách nào để ngăn trình xử lý sự kiện bị thu thập rác khi thiếu từ DOM?

Tôi hiểu rằng tôi chỉ có thể gán lại chức năng click(), nhưng vì tôi đang sử dụng thư viện bên ngoài (jquery ui), tôi thực sự không biết nó làm gì với các điều khiển của tôi. Tôi chỉ muốn các sự kiện của họ được phục hồi như trước đây.

<div id="container"> 
    <p>This container has a button, which will forget its click()...</p> 
    <input id="testbutton" type="button" value="Click Me!"/> 
</div> 

<script type="text/javascript"> 
    $(function(){ 
     $("#testbutton").click(
      function(){ 
       alert("Button has been clicked!"); 
     }) 
    }); 
</script> 

<div> 
    <p>... when this button reseats html</p> 
    <input id="actionbutton" type="button" value="Toggle"/> 
</div> 

<script type="text/javascript"> 
    var toggle = false; 
    var html; 
    $(function(){ 
     $("#actionbutton").click(
      function(){ 
       toggle = !toggle; 
       if(toggle){ 
        html = $("#container").html(); 
        $("#container").html(""); 
       } else $("#container").html(html); 
     }) 
    }); 
</script> 

jfiddle minh họa sự cố tôi đang gặp phải.

+0

Và thay thế là không ghi đè lên html trong vùng chứa, nhưng thay vào đó, hãy sử dụng phương pháp tách để loại bỏ và sau đó thêm nó trở lại dom - http://jsfiddle.net/8S5E4/4/. Không có vẻ như đây là những gì bạn muốn mặc dù (dựa trên các ý kiến ​​trong fiddle) –

Trả lời

4

câu trả lời đơn giản: sử dụng .live

$(function(){ 
    $("#testbutton").live('click', 
     function(){ 
      alert("Button has been clicked!"); 
    }) 
}); 

Đây là fiddle Cập nhật: http://jsfiddle.net/mrchief/8S5E4/1/

Giải thích: Khi bạn thay đổi DOM, trình xử lý sự kiện được đính kèm phần tử cũng bị loại bỏ. Sử dụng .live gắn các trình xử lý sự kiện vào 'body' (và lọc theo phần tử DOM) để nó 'sống' ngay cả sau khi xóa/thêm cùng một phần tử DOM.

Bạn có thể đạt được hiệu quả tương tự sử dụng .delegate thêm:

$(function(){ 
    $('#container').delegate('#testbutton', 'click', 
     function(){ 
      alert("Button has been clicked!"); 
    }) 
}); 

fiddle sử dụng .delegate: http://jsfiddle.net/mrchief/8S5E4/6/

tôi sẽ khuyên bạn sử dụng .delegate qua .live cho:

  • Bạn có thể hủy sự kiện bọt . Khi bạn sử dụng live, sự kiện sẽ phát ra tất cả các cách đến body và sau đó trình xử lý của bạn được gọi, vì vậy không có cách nào để hủy bong bóng của nó. (Theo jQuery 1.4, điều này có thể được ngăn chặn bằng cách sử dụng một đối số ngữ cảnh: http://api.jquery.com/live/)
  • Vì bạn đang gắn vào một phần tử DOM cụ thể, nó không được gọi mỗi lần có một lần nhấp vào bất kỳ phần tử DOM nào khác trên cơ thể và do đó, có hiệu quả hơn vì nó phải làm ít công việc hơn.

Dưới đây là một bài viết tuyệt vời giải thích rõ ràng về số differences between live, delegate and bind và thảo luận về các sắc thái của mỗi cách tiếp cận. Cảm ơn @andyb vì đã chỉ liên kết này ra.

+0

Cảm ơn rất nhiều vì một câu trả lời rất toàn diện! Tôi vẫn còn có một vấn đề mặc dù, bởi vì nó không thực sự tôi, những người làm cho các sự kiện click() ở nơi đầu tiên, đó là jquery ui. Những gì tôi sẽ làm là đăng một câu hỏi khác và trình bày vấn đề cụ thể đó. – Gleno

+0

Rất vui được trợ giúp! Đừng quên chấp nhận câu trả lời! – Mrchief

2

jQuery đoàn sự kiện để giải cứu

$("#container").delegate('#testbutton', 'click', 
    function(){ 
     alert("Button has been clicked!"); 
}); 

Lưu ý: .delegate()is more efficient hơn .live()

+0

chỉ cần quan tâm: Liệu vấn đề hiệu quả vẫn như nhau? Bài viết bạn đăng hơn một năm và được viết trong thời gian jquery 1.4. Có phải jQuery - Team đã giải quyết vấn đề này hay tôi nên bắt đầu sử dụng ủy nhiệm cho những trường hợp này? – GNi33

+0

Kể từ 1,4, sống mất một đối số bối cảnh quá '$ (" div.clickme ", $ (" # container ") [0]). Sống (" click ", function() { // Trình xử lý trực tiếp được gọi là }); ': http://api.jquery.com/live/ – Mrchief

+1

@ GNi33, hãy xem câu trả lời của @ Mrchief để biết thêm một số lý do khiến đại biểu tốt hơn, cũng [một bài viết gần đây hơn] (http://www.alfajango.com/blog/the-difference-between-jquerys-bind-live-and-delegate /) về sự khác biệt. Điều đó nói rằng, tôi đồng ý rằng bài viết liên kết là cũ và rằng nhóm jQuery có thể đã thắt chặt '.live()' kể từ 1.4 – andyb

2

này đang xảy ra bởi vì bạn đang ràng buộc một sự kiện để #testbutton mà cuộc sống bên của #container trên tài liệu đã sẵn sàng. Khi bạn xóa HTML của #container, bạn cũng sẽ mất rằng #testbutton sự kiện nhấp chuột bị ràng buộc. Thay vào đó, phần tử tham chiếu sự kiện nhấp chuột không còn tồn tại nữa.

Nếu bạn muốn sự kiện nút đó tồn tại, hãy thử sử dụng live() ràng buộc hoặc delegate() sự kiện từ phần tử gốc.


Sử dụng live()

$(function(){ 
    $("#testbutton").live("click", function() { 
     alert("Button has been clicked!"); 
    }) 
}); 

Đính kèm một handler cho sự kiện này cho tất cả các yếu tố đó phù hợp với bộ chọn hiện tại, bây giờ và trong tương lai.


Sử dụng delegate()

$(function(){ 
    $("#container").delegate("#testbutton", "click", function() { 
     alert("Button has been clicked!"); 
    }) 
}); 

Đính kèm một handler cho một hoặc nhiều sự kiện cho tất cả các yếu tố phù hợp với bộ chọn, ngay bây giờ hoặc trong tương lai, dựa trên một tập hợp cụ thể của phần tử gốc.

Các vấn đề liên quan