96

.on()用来绑定页面加载后创建的 div 事件。它适用于单击、鼠标输入...但我需要知道何时添加了 MyClass 类的新 div。我正在寻找这个:

$('#MyContainer').on({

  wascreated: function () { DoSomething($(this)); }

}, '.MyClass');

我该怎么做呢?我已经设法在没有插件的情况下编写了整个应用程序,并且我想保持这种方式。

谢谢。

4

6 回答 6

111

以前可以挂钩到 jQuery 的domManip方法来捕获所有 jQuery dom 操作并查看插入了哪些元素等,但是 jQuery 团队在 jQuery 3.0+ 中关闭了它,因为以这种方式挂钩到 jQuery 方法通常不是一个好的解决方案,而且他们'已经做到了,因此内部domManip方法在核心 jQuery 代码之外不再可用。

突变事件也已被弃用,因为以前可以做类似的事情

$(document).on('DOMNodeInserted', function(e) {
    if ( $(e.target).hasClass('MyClass') ) {
       //element with .MyClass was inserted.
    }
});

应该避免这种情况,而今天应该使用 Mutation Observers 来代替,它的工作原理是这样的

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        console.log(mutation)
        if (mutation.addedNodes && mutation.addedNodes.length > 0) {
            // element added to DOM
            var hasClass = [].some.call(mutation.addedNodes, function(el) {
                return el.classList.contains('MyClass')
            });
            if (hasClass) {
                // element has class `MyClass`
                console.log('element ".MyClass" added');
            }
        }
    });
});

var config = {
    attributes: true,
    childList: true,
    characterData: true
};

observer.observe(document.body, config);
于 2012-05-02T14:17:58.017 回答
55

这是我的插件,可以做到这一点 - jquery.initialize

用法与您使用.each函数相同,但.initialize在元素上使用函数,不同之处.each在于它还将初始化将来添加的元素而无需任何额外代码 - 无论您是否使用 AJAX 或其他任何方式添加它。

Initialize 的语法与 .each 函数完全相同

$(".some-element").initialize( function(){
    $(this).css("color", "blue");
});

但是现在如果新的元素匹配 .some-element 选择器将出现在页面上,它将被立即初始化。添加新项目的方式并不重要,您不需要关心任何回调等。

$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!

插件基于MutationObserver

于 2015-02-04T01:03:37.297 回答
25

在查看了这篇文章和其他几篇文章后,我试图将我认为最好的东西提炼成简单的东西,让我能够检测何时插入了一类元素,然后对这些元素采取行动

function onElementInserted(containerSelector, elementSelector, callback) {

    var onMutationsObserved = function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes.length) {
                var elements = $(mutation.addedNodes).find(elementSelector);
                for (var i = 0, len = elements.length; i < len; i++) {
                    callback(elements[i]);
                }
            }
        });
    };

    var target = $(containerSelector)[0];
    var config = { childList: true, subtree: true };
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    var observer = new MutationObserver(onMutationsObserved);    
    observer.observe(target, config);

}

onElementInserted('body', '.myTargetElement', function(element) {
    console.log(element);
});

对我来说重要的是,这允许a)目标元素存在于“添加的节点”中的任何深度,b)仅在最初插入时处理元素的能力(无需搜索整个文档设置或忽略“已处理”标志)。

于 2016-07-22T03:08:58.957 回答
17

3年后的经验,这就是我听“添加到DOM的某个类的元素”的方式html():您只需在jQuery函数中添加一个钩子,如下所示:

function Start() {

   var OldHtml = window.jQuery.fn.html;

   window.jQuery.fn.html = function () {

     var EnhancedHtml = OldHtml.apply(this, arguments);

     if (arguments.length && EnhancedHtml.find('.MyClass').length) {

         var TheElementAdded = EnhancedHtml.find('.MyClass'); //there it is
     }

     return EnhancedHtml;
   }
}

$(Start);

如果您使用的是 jQuery,这很有效,我就是这样做的。而且它不依赖于浏览器特定的事件DOMNodeInserted,它不是跨浏览器兼容的。我还为.prepend()

总的来说,这对我来说就像一个魅力,希望对你也一样。

于 2015-05-20T19:57:00.580 回答
6

你可以使用突变事件

http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mutationevents

编辑

来自 MDN:https ://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events

已弃用 此功能已从 Web 中删除。尽管某些浏览器可能仍然支持它,但它正在被删除。不要在旧项目或新项目中使用它。使用它的页面或 Web 应用程序可能随时中断。

突变观察者是 DOM4 中突变事件的提议替代品。它们将包含在 Firefox 14 和 Chrome 18 中。

https://developer.mozilla.org/en/docs/Web/API/MutationObserver

MutationObserver为开发人员提供了一种对 DOM 中的更改做出反应的方法。它旨在替代 DOM3 事件规范中定义的突变事件。

示例用法

以下示例取自http://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/

// select the target node
var target = document.querySelector('#some-id');

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });    
});

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

// later, you can stop observing
observer.disconnect();
于 2012-05-02T14:15:51.803 回答
1

adeneo 的答案有两个补充:

(1) 我们可以换行

return el.classList.contains('MyClass');

if( el.classList ) {
    return el.classList.contains('MyClass');
} else {
    return false;
}

所以我们不会看到"Uncaught TypeError: Cannot read property 'contains' of undefined"错误。

(2) add subtree: trueinconfig在所有添加的元素中递归查找添加的节点。

于 2020-06-01T08:09:24.613 回答