320

我有一个 div,它的内容一直在变化,无论是ajax requestsjquery functions等等blur

有没有办法可以在任何时间点检测到我的 div 上的任何更改?

我不想使用任何间隔或检查的默认值。

这样的事情会做

$('mydiv').contentchanged() {
 alert('changed')
}
4

13 回答 13

483

如果您不想使用计时器并检查innerHTML,您可以尝试此事件

$('mydiv').on('DOMSubtreeModified', function(){
  console.log('changed');
});

更多细节和浏览器支持数据在这里

于 2013-04-30T04:41:36.213 回答
104

使用 Javascript MutationObserver

// Select the target node.
var target = document.querySelector('mydiv')

// Create an observer instance.
var observer = new MutationObserver(function(mutations) {
    console.log(target.innerText);   
});

// Pass in the target node, as well as the observer options.
observer.observe(target, {
    attributes:    true,
    childList:     true,
    characterData: true
});

有关详细信息,请参阅 MDN 文档;这应该适用于几乎所有当前的浏览器,包括 IE11。

于 2017-03-15T09:36:23.237 回答
70

由于$("#selector").bind()已弃用,您应该使用:

$("body").on('DOMSubtreeModified', "#selector", function() {
    // code here
});
于 2017-03-15T08:57:00.693 回答
48

你可以试试这个

$('.myDiv').bind('DOMNodeInserted DOMNodeRemoved', function() {

});

但这可能不适用于 Internet Explorer,尚未测试

于 2013-05-10T11:40:29.540 回答
34

您正在寻找MutationObserverMutation Events。既不受任何地方的支持,也不受开发人员世界的喜爱。

如果您知道(并且可以确保)div 的大小会发生变化,则可以使用跨浏览器调整大小事件

于 2013-03-27T11:51:23.813 回答
26

以下代码适用于我:

$("body").on('DOMSubtreeModified', "mydiv", function() {
    alert('changed');
});
于 2017-03-22T10:26:55.827 回答
16

这个问题没有内置的解决方案,这是您的设计和编码模式的问题。

您可以使用发布者/订阅者模式。为此,您可以使用 jQuery 自定义事件或您自己的事件机制。

第一的,

function changeHtml(selector, html) {
    var elem = $(selector);
    jQuery.event.trigger('htmlchanging', { elements: elem, content: { current: elem.html(), pending: html} });
    elem.html(html);
    jQuery.event.trigger('htmlchanged', { elements: elem, content: html });
}

现在您可以订阅 divhtmlchanged/divhtmlchanged 事件,如下所示,

$(document).bind('htmlchanging', function (e, data) {
    //your before changing html, logic goes here
});

$(document).bind('htmlchanged', function (e, data) {
    //your after changed html, logic goes here
});

现在,您必须通过此changeHtml()功能更改您的 div 内容更改。因此,您可以监视或可以相应地进行必要的更改,因为绑定包含信息的回调数据参数。

您必须像这样更改 div 的 html;

changeHtml('#mydiv', '<p>test content</p>');

而且,您可以将它用于除输入元素之外的任何 html 元素。无论如何,您可以修改它以与任何元素一起使用。

于 2013-05-24T09:26:49.120 回答
9

使用Mozilla提供的这个片段中看到的MutationObserver,并改编自这篇博客文章

或者,您可以使用此链接中看到的 JQuery 示例

Chrome 18+、Firefox 14+、IE 11+、Safari 6+

// Select the node that will be observed for mutations
var targetNode = document.getElementById('some-id');

// Options for the observer (which mutations to observe)
var config = { attributes: true, childList: true };

// Callback function to execute when mutations are observed
var callback = function(mutationsList) {
    for(var mutation of mutationsList) {
        if (mutation.type == 'childList') {
            console.log('A child node has been added or removed.');
        }
        else if (mutation.type == 'attributes') {
            console.log('The ' + mutation.attributeName + ' attribute was modified.');
        }
    }
};

// Create an observer instance linked to the callback function
var observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(targetNode, config);

// Later, you can stop observing
observer.disconnect();
于 2018-05-23T17:20:00.090 回答
3

尝试了上面给出的一些答案,但那些火灾事件两次。如果您可能需要相同的解决方案,这是可行的解决方案。

$('mydiv').one('DOMSubtreeModified', function(){
    console.log('changed');
});
于 2020-08-28T14:24:29.113 回答
2

您可以将 div 的旧 innerHTML 存储在变量中。设置间隔以检查旧内容是否与当前内容匹配。当这不是真的做某事。

于 2013-03-27T18:46:08.167 回答
2

试试 MutationObserver:

浏览器支持:http ://caniuse.com/#feat=mutationobserver

<html>
  <!-- example from Microsoft https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/dev-guide/dom/mutation-observers/ -->

  <head>
    </head>
  <body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script type="text/javascript">
      // Inspect the array of MutationRecord objects to identify the nature of the change
function mutationObjectCallback(mutationRecordsList) {
  console.log("mutationObjectCallback invoked.");

  mutationRecordsList.forEach(function(mutationRecord) {
    console.log("Type of mutation: " + mutationRecord.type);
    if ("attributes" === mutationRecord.type) {
      console.log("Old attribute value: " + mutationRecord.oldValue);
    }
  });
}
      
// Create an observer object and assign a callback function
var observerObject = new MutationObserver(mutationObjectCallback);

      // the target to watch, this could be #yourUniqueDiv 
      // we use the body to watch for changes
var targetObject = document.body; 
      
// Register the target node to observe and specify which DOM changes to watch
      
      
observerObject.observe(targetObject, { 
  attributes: true,
  attributeFilter: ["id", "dir"],
  attributeOldValue: true,
  childList: true
});

// This will invoke the mutationObjectCallback function (but only after all script in this
// scope has run). For now, it simply queues a MutationRecord object with the change information
targetObject.appendChild(document.createElement('div'));

// Now a second MutationRecord object will be added, this time for an attribute change
targetObject.dir = 'rtl';


      </script>
    </body>
  </html>

于 2016-11-21T14:58:09.833 回答
1

DOMSubtreeModified不是一个好的解决方案。如果您决定更改事件处理程序中的 DOM,它可能会导致无限循环,因此它已在许多浏览器中被禁用。MutationObserver是更好的答案。

MDN 文档

const onChangeElement = (qSelector, cb)=>{
 const targetNode = document.querySelector(qSelector);
 if(targetNode){
    const config = { attributes: true, childList: false, subtree: false };
    const callback = function(mutationsList, observer) {
        cb($(qSelector))
    };
    const observer = new MutationObserver(callback);
    observer.observe(targetNode, config);
 }else {
    console.error("onChangeElement: Invalid Selector")
 }
}

你可以像这样使用它,

onChangeElement('mydiv', function(jqueryElement){
   alert('changed')
})
于 2020-11-09T06:25:48.957 回答
0

将一些内容添加到 div,无论是通过 jQuery 还是直接通过 de DOM-API,默认为该.appendChild()函数。你可以做的是覆盖.appendChild()当前对象的功能并在其中实现一个观察者。现在已经覆盖了我们的.appendChild()函数,我们需要从另一个对象借用该函数才能附加内容。因此,我们调用.appendChild()另一个 div 来最终附加内容。当然,这也适用于.removeChild().

var obj = document.getElementById("mydiv");
    obj.appendChild = function(node) {
        alert("changed!");

        // call the .appendChild() function of some other div
        // and pass the current (this) to let the function affect it.
        document.createElement("div").appendChild.call(this, node);
        }
    };

在这里你可以找到一个幼稚的例子。我猜你可以自己扩展它。 http://jsfiddle.net/RKLmA/31/

顺便说一句:这表明 JavaScript 符合 OpenClosed 原则。:)

于 2013-03-27T11:58:40.090 回答