Phát hiện các thay đổi nội dung phần tử với jQuery


113

change() chức năng hoạt động và phát hiện các thay đổi trên các phần tử biểu mẫu, nhưng có cách nào để phát hiện khi nào nội dung của phần tử DOM đã bị thay đổi không?

Điều này không hoạt động, trừ khi #contentlà một phần tử biểu mẫu

$("#content").change( function(){
    // do something
});

Tôi muốn điều này kích hoạt khi thực hiện một số việc như:

$("#content").html('something');

Ngoài ra html()hoặc append()chức năng không có một cuộc gọi lại.

Bất kỳ đề xuất?


câu hỏi cũ mà tôi biết, nhưng hãy kiểm tra câu trả lời của tôi để có giải pháp thanh lịch stackoverflow.com/a/23826615/744975
Andrew Atkinson

Câu trả lời:


26

Đây là những sự kiện đột biến .

Tôi chưa sử dụng các API sự kiện đột biến trong jQuery, nhưng một tìm kiếm lướt qua đã dẫn tôi đến dự án này trên GitHub. Tôi không biết về sự trưởng thành của dự án.


17
Plugin sự kiện đột biến này sẽ không hoạt động, bởi vì nó chỉ nối các sự kiện vào các phương thức đột biến jQuery. Chúng được kích hoạt khi chính jQuery cố gắng thay đổi các phần tử, nhưng không phải khi các phần tử được thay đổi từ bên ngoài jQuery. Họ không xem các thay đổi trên tài liệu. Thay vào đó, hãy xem plugin nhỏ này: stackoverflow.com/questions/3233991/jquery-watch-div/…
Sebastián Grignoli,

10
Googling và đăng một liên kết đến một thư viện mà bạn chưa bao giờ thử thực sự không hữu ích lắm. (Bình luận bởi vì tôi đã nhắc khi downvoting.)
Dừng vu khống Monica Cellio


Sự thay thế cho các sự kiện đột biến dường như là MutationObservers .
WoodrowShigeru

69

Tôi biết bài đăng này đã được một năm tuổi, nhưng tôi muốn cung cấp một cách tiếp cận giải pháp khác cho những người gặp vấn đề tương tự:

  1. Sự kiện thay đổi jQuery chỉ được sử dụng trên các trường nhập của người dùng vì nếu bất kỳ thứ gì khác được thao tác (ví dụ: div), thì thao tác đó đến từ mã. Vì vậy, hãy tìm nơi thao tác xảy ra và sau đó thêm bất cứ thứ gì bạn cần vào đó.

  2. Nhưng nếu điều đó không thể thực hiện được vì bất kỳ lý do gì (bạn đang sử dụng một plugin phức tạp hoặc không thể tìm thấy bất kỳ khả năng "gọi lại" nào) thì cách tiếp cận jQuery mà tôi đề xuất là:

    a. Để thao tác DOM đơn giản, hãy sử dụng chuỗi và duyệt jQuery,$("#content").html('something').end().find(whatever)....

    b. Nếu bạn muốn làm điều gì đó khác, hãy sử dụng jQuery bindvới sự kiện tùy chỉnh vàtriggerHandler

    $("#content").html('something').triggerHandler('customAction');
    
    $('#content').unbind().bind('customAction', function(event, data) {
       //Custom-action
    });

Đây là liên kết đến trình xử lý trình kích hoạt jQuery: http://api.jquery.com/triggerHandler/


1
suy nghĩ cuối cùng. mặc dù điều đó nên được khá toàn diện trên: bạn có thể cập nhật các giá trị của một trường nhập ẩn với điều đó của # content html và sau đó liên kết các sự kiện thay đổi đến lĩnh vực đầu vào ẩn :) nhiều lựa chọn
Kyle

7
+1 "Tìm nơi xảy ra thao tác, sau đó thêm bất cứ thứ gì bạn cần vào đó." Cố định vấn đề của tôi trong 2 giây mà không có bất kỳ hacks / plugins :)
Hartley Brody

Thay đổi duy nhất tôi đề xuất ở đây là bindtrình xử lý đang mong đợi trình xử lý của bạn trả về a bool.
Serj Sagan,

15

Trình duyệt sẽ không kích hoạt sự kiện onchange cho <div> các phần tử.

Tôi nghĩ lý do đằng sau điều này là những yếu tố này sẽ không thay đổi trừ khi được sửa đổi bởi javascript. Nếu bạn đã phải tự mình sửa đổi phần tử (chứ không phải người dùng làm việc đó), thì bạn có thể chỉ cần gọi mã đi kèm thích hợp cùng lúc để sửa đổi phần tử, như sau:

 $("#content").html('something').each(function() { });

Bạn cũng có thể kích hoạt một sự kiện như sau theo cách thủ công:

 $("#content").html('something').change();

Nếu cả hai giải pháp này đều không phù hợp với tình huống của bạn, bạn có thể vui lòng cung cấp thêm thông tin về những gì bạn đang cố gắng hoàn thành một cách cụ thể không?


11
Điều này giả định rằng bạn đã viết tất cả javascript, có thể không đúng như vậy.
Myster

CẢM ƠN BẠN!!!! Điều này chỉ giúp tôi giải quyết một vấn đề mà tôi đã nhìn chằm chằm trong 6 giờ.
Jordan Parmer

Chính xác những gì tôi cần.
smac89

15

còn http://jsbin.com/esepal/2

$(document).bind("DOMSubtreeModified",function(){
  console.log($('body').width() + ' x '+$('body').height());
})

Sự kiện này đã không được dùng nữa để thay thế cho API trình quan sát đột biến


1
không phải là một ý tưởng tồi, mặc dù tôi tự hỏi nó có bao nhiêu hỗ trợ. developer.mozilla.org/en/DOM/DOM_event_reference/…
Elzo Valugi

Làm thế nào để bạn giám sát một yếu tố cụ thể cho các thay đổi? Hiện tài liệu giám sát toàn bộ trang.
Patoshi パ ト シ




3

Nó không hoàn toàn là một câu trả lời jQuery - nhưng hữu ích khi đề cập đến để gỡ lỗi.

Trong Firebug, bạn có thể nhấp chuột phải vào một phần tử trong cây DOM và thiết lập 'Break on Attribute Change':

Nhấp chuột phải vào phần tử trong Firebug với Break on Attribute Change được đánh dấu

Khi một thuộc tính được thay đổi trong tập lệnh, cửa sổ gỡ lỗi sẽ xuất hiện và bạn có thể theo dõi những gì nó đang diễn ra. Ngoài ra còn có một tùy chọn để chèn phần tử và loại bỏ phần tử bên dưới (bị che khuất một cách vô ích bởi cửa sổ bật lên trong màn hình).


1
Điều này hữu ích, nhưng không chính xác những gì anh ấy đang yêu cầu. Điều này sẽ phát hiện những thứ như khi một lớp thay đổi hoặc khi một thuộc tính kiểu được thêm vào hoặc thay đổi. Nó sẽ không kiểm tra khi nội dung bên trong nút thay đổi. Ví dụ: nếu một số javascript ở đâu đó thay đổi một nút từ <span> xin chào </span> thành <span> World </span>, điều này sẽ không phát hiện ra nó
Joshua Soileau 19/01/16



1

Thường thì một cách đơn giản và hiệu quả để đạt được điều này là theo dõi thời gian và vị trí bạn đang sửa đổi DOM.

Bạn có thể làm điều này bằng cách tạo một chức năng trung tâm luôn chịu trách nhiệm sửa đổi DOM. Sau đó, bạn thực hiện bất kỳ thao tác dọn dẹp nào bạn cần đối với phần tử đã sửa đổi từ bên trong hàm này.

Trong một ứng dụng gần đây, tôi không cần hành động ngay lập tức vì vậy tôi đã sử dụng lệnh gọi lại cho hàm tải thủ công (), để thêm một lớp vào bất kỳ phần tử đã sửa đổi nào và sau đó cập nhật tất cả các phần tử đã sửa đổi vài giây một lần bằng bộ đếm thời gian setInterval.

$($location).load("my URL", "", $location.addClass("dommodified"));

Sau đó, bạn có thể xử lý nó theo cách bạn muốn - ví dụ:

setInterval("handlemodifiedstuff();", 3000); 
function handlemodifiedstuff()
{
    $(".dommodified").each(function(){/* Do stuff with $(this) */});
}

3
Điều này giả định rằng bạn đã viết tất cả javascript, có thể không đúng như vậy.
Myster

1

Bạn có thể thêm tùy chọn gọi lại vào hàm html (hoặc bất kỳ):

$.fn.oldHtml = $.fn.html;
$.fn.html = function(html,fn){
  fn = fn || function(){};
  var result =  this.oldHtml(html);
  fn();
  return result;
};
$('body').html(11,function(){alert("haha");});

Demo tại đây.

Bạn thực hiện thay đổi trên một số phần tử, không phải phần tử bị buộc phải thay đổi bởi một thứ gì đó mà bạn phải nắm bắt.


Tôi đã phải giải quyết vấn đề này ngày hôm nay. Tôi không thể chỉnh sửa mã thực sự được gọi là html () vì nó nằm trong thư viện của bên thứ ba. Một phiên bản sửa đổi của điều này là hoàn hảo cho tôi. Tôi đã làm điều này: $ .fn.oldHtml = $ .fn.html (); $ .fn.html = function (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e);} Bây giờ tôi có thể liên kết bất kỳ sự kiện nào tôi muốn với sự kiện afterHtmlChange mới được tạo trên bất kỳ phần tử nào, sự kiện này sẽ kích hoạt bất cứ khi nào có bất kỳ thứ gì gọi html () fn của jQuery.
Daniel Howard

Rất tiếc, nhầm lẫn nhẹ. Fn trong nhận xét của tôi ở trên phải là: function (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e); trả về kết quả;}
Daniel Howard

0

Tôi đã viết một đoạn mã sẽ kiểm tra sự thay đổi của một phần tử trong một sự kiện.

Vì vậy, nếu bạn đang sử dụng mã javascript của bên thứ ba hoặc thứ gì đó và bạn cần biết khi nào thứ gì đó xuất hiện hoặc thay đổi khi bạn nhấp vào thì bạn có thể.

Đối với đoạn mã dưới đây, giả sử bạn cần biết khi nào nội dung bảng thay đổi sau khi bạn nhấp vào một nút.

$('.button').live('click', function() {

            var tableHtml = $('#table > tbody').html();
            var timeout = window.setInterval(function(){

                if (tableHtml != $('#table > tbody').
                    console.log('no change');
                } else {
                    console.log('table changed!');
                    clearInterval(timeout);
                }

            }, 10);
        });

Mã giả:

  • Khi bạn nhấp vào một nút
  • html của phần tử bạn muốn thay đổi đã được nắm bắt
  • sau đó chúng tôi liên tục kiểm tra html của phần tử
  • khi chúng tôi nhận thấy html khác biệt, chúng tôi ngừng kiểm tra

0

Chúng ta có thể đạt được điều này bằng cách sử dụng Sự kiện đột biến . Theo www.w3.org, Mô-đun sự kiện đột biến được thiết kế để cho phép thông báo về bất kỳ thay đổi nào đối với cấu trúc của tài liệu, bao gồm cả sửa đổi đính kèm và văn bản. Để biết thêm chi tiết SỰ KIỆN MUTATION

Ví dụ :

$("body").on('DOMSubtreeModified', "#content", function() {
    alert('Content Modified'); // do something
});

Điều này đã không được chấp nhận trong một thời gian. Người ta nên sử dụng Trình quan sát đột biến (cùng một khái niệm)
Carles Alcolea

-3

Không thể, tôi tin rằng có một sự kiện thay đổi nội dung nhưng nó chắc chắn không phải là x-browser

Tôi có nên nói rằng không thể thực hiện được nếu không có một số khoảng thời gian khó chịu trong nền!


21
không gì là không thể!
jrharshath 07-07-09
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.