jQuery事件:检测对div的html / text的更改


265

我有一个div,其内容一直在变化ajax requests,例如jquery functionsblur等等。

有什么方法可以随时检测div上的任何更改吗?

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

这样的事情会做

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


14
@Rob将keypress事件绑定到contenteditable <div>元素。我不确定那里的解决方案是否适用于此。他们绝对不会对元素的内容进行任何程序更改。
安东尼·格里斯

Answers:


407

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

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

更多详细信息和浏览器支持数据在此处

注意:在较新的jQuery版本中,不建议使用bind(),因此应改为使用on():

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

14
请记住,IE8(及以下)不支持DOMSubtreeModified。
加文


3
Mozilla 33:归因于元素<body>的递归。需要寻找其他方法
Chaki_Black 2014年

17
严重的是,请勿使用此事件,因为它会导致您所有的工作崩溃,并且一直被解雇。而是使用$('。myDiv')。bind('DOMNodeInserted DOMNodeRemoved',function(){});下的事件。
George SEDRA '16

19
此方法已被弃用!而是使用:$("body").on('DOMSubtreeModified', "mydiv", function() { });
Asif

55

使用Javascript MutationObserver

  //More Details https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
 // select the target node
var target = document.querySelector('mydiv')
// create an observer instance
var observer = new MutationObserver(function(mutations) {
  console.log($('mydiv').text());   
});
// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true };
// pass in the target node, as well as the observer options
observer.observe(target, config);

6
这是正确的答案,因为现在比使用DOMSubtreeModified更受青睐
Joel Davey

3
即使我给出了正确的选择器,我也对此出错。“ VM21504:819未捕获的TypeError:无法在'MutationObserver'上执行'观察':参数1的类型不是'节点'。”
萨米尔


42

你可以试试这个

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

});

但这可能在Internet Explorer中不起作用,还没有测试



3
注意!:如果将它用作触发器,并且对该页面进行了很多更改,它将使您的函数运行X次(甚至X = 1,000或更多),这可能会非常低效。一个简单的解决方案是定义一个“正在运行的”布尔值var,它将... if(running == true){return} ...如果已经在运行,则不运行您的代码。在if逻辑之后立即设置running = true,在函数退出之前将running = false设置。您还可以使用计时器将功能限制为只能每X秒运行一次。running = true; setTimeout(function(){running = false},5000); (或更好的东西)
JxAxMxIxN

我在一个具有添加和删除选项的选择框上使用了此功能。添加项目时效果很好,但是删除似乎落后了1个项目。删除最后一个选项后,它将不会触发。
CodeMonkey

2
@JxAxMxIxN您还可以通过再次清除并设置超时来增加超时计时器:clearTimeout(window.something); window.something = setTimeout(...);
Ctrl-C

同意-您的路是要走的路-自从学习Python之后,我已经清除了我在多种语言中的许多不良编码实践(不是全部,只是很多;)
JxAxMxIxN

33

您正在寻找MutationObserverMutation Events。开发者世界既没有得到所有人的支持,也没有太过热情地看待它们。

如果您知道(并可以确保)div的大小将改变,则可以使用crossbrowser resize事件


1
这是一个。具体来说,是DOMSubtreeModified。您可能会发现变异摘要库很有用,并且此DOM Tree Events列表也是如此。
BenjaminRH


9
万一其他人不得不尝试遍历所有内容,这是正确的答案。过去的浏览器支持突变事件,而现代浏览器将支持突变观察者,将来也将支持。请参阅支持链接:CANIUSE变异观察员
Josh Mc

20

以下代码对我有用。

$("body").on('DOMSubtreeModified', "mydiv", function() {
    alert('changed');
});

希望它能帮助某人:)


这与@Artley
Black的

@黑色谢谢!我刚刚检查了Artley的答案。下次我会照顾的。
Sanchit Gupta,

17

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

您可以使用发布者/订阅者模式。为此,您可以使用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 });
}

现在,您可以按以下方式订阅divhtmlchanging / 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元素。无论如何,您都可以修改它以与任何元素一起使用。


要观察和处理特定元素的变化,只需将changeHtml函数修改为使用'elem.trigger(...)'而不是'jQuery.event.trigger(...)',然后像这样绑定到元素$('#my_element_id')。on('htmlchanged',function(e,data){...}
KenB 2014年

8
“这是您的设计和编码模式的问题”,如果包含第三方脚本,因此您无法控制其源代码,该怎么办?但是您需要检测它们对一个div的更改?
DrLightman '16

@DrLightman的经验法则是选择提供回调事件的第三方库
Marcel Djaman

8

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();

3

您可以将div的旧innerHTML存储在变量中。设置间隔以检查旧内容是否与当前内容匹配。如果这不是真的,那就做点什么。


1

尝试使用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>


0

默认情况下,通过jQuery或直接通过DOM-API向div添加一些内容.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原理。:)


它不适用于追加子项...实际上我通过其他功能修改了它的html。
BoqBoq

像removeChild()replaceChild()等。但是您对innerHTML的看法是正确的。您应该以某种方式避免它。
Andries
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.