jQuery"on create"事件,用于动态创建的元素

Cab*_*ero 72 javascript jquery combobox

我需要能够动态创建<select>元素并将其转换为jQuery .combobox().这应该是元素创建事件,而不是某些"click"事件,在这种情况下我可以使用jQuery .on().

这样的事情存在吗?

$(document).on("create", "select", function() {
    $(this).combobox();
}
Run Code Online (Sandbox Code Playgroud)

我不愿意使用livequery,因为它已经过时了.

更新提到的select/combobox通过ajax加载到jQuery颜色框(模态窗口),因此问题 - 我只能使用colorbox启动组合框onComplete,但是在更改一个组合框时,必须动态创建另一个select/combobox,因此我需要一个检测元素创建的更通用方法(select在本例中).

UPDATE2为了尝试进一步解释问题 - 我有select/combobox递归创建的元素,里面还有很多启动代码.combobox(),因此如果我使用经典的方法,比如在@ bipen的答案中,我的代码会膨胀到疯狂的级别.希望这能更好地解释问题.

UPDATE3感谢大家,我现在明白,因为DOMNodeInserted在DOM变异中遗漏了一个空白,并且没有解决这个问题的方法.我只需要重新考虑我的申请.

Cod*_*uth 53

您可以onDOMNodeInserted事件得到,当它在你的代码添加到文档中的事件.

$('body').on('DOMNodeInserted', 'select', function () {
      //$(this).combobox();
});

$('<select>').appendTo('body');
$('<select>').appendTo('body');
Run Code Online (Sandbox Code Playgroud)

摆弄在这里:http://jsfiddle.net/Codesleuth/qLAB2/3/

编辑:阅读后我只需要仔细检查DOMNodeInserted不会导致浏览器出现问题.2010年的这个问题表明IE不支持该事件,所以如果可以,请测试它.

看到这里:[链接] 警告!DOMNodeInserted事件类型在本规范中定义,以供参考和完整,但此规范不推荐使用此事件类型.

  • 既然你没有尝试过这个问题,我会说这是不公平的投票.无论如何,我在这里帮不了你. (17认同)
  • 是的,你说得对。我会修改这个答案,但老实说我不确定你是否应该使用它,因为现在不推荐使用`DOMNodeInserted`。 (2认同)

Yuk*_*élé 20

您可以使用DOMNodeInserted变异事件(无需委托):

$('body').on('DOMNodeInserted', function(e) {
    var target = e.target; //inserted element;
});
Run Code Online (Sandbox Code Playgroud)

编辑:突变事件弃用,使用突变观察者,而不是


And*_*ers 10

如其他几个答案所述,不建议使用突变事件,因此应改用MutationObserver。既然还没有人提供任何细节,那就去吧...

基本的JavaScript API

MutationObserver的API非常简单。它不像突变事件那么简单,但是仍然可以。

function callback(records) {
  records.forEach(function (record) {
    var list = record.addedNodes;
    var i = list.length - 1;
    
	for ( ; i > -1; i-- ) {
	  if (list[i].nodeName === 'SELECT') {
	    // Insert code here...
	    console.log(list[i]);
	  }
	}
  });
}

var observer = new MutationObserver(callback);

var targetNode = document.body;

observer.observe(targetNode, { childList: true, subtree: true });
Run Code Online (Sandbox Code Playgroud)
<script>
  // For testing
  setTimeout(function() {
    var $el = document.createElement('select');
    document.body.appendChild($el);
  }, 500);
</script>
Run Code Online (Sandbox Code Playgroud)

让我们分解一下。

var observer = new MutationObserver(callback);
Run Code Online (Sandbox Code Playgroud)

这将创建观察者。观察者还什么都没看。这就是事件监听器的附加位置。

observer.observe(targetNode, { childList: true, subtree: true });
Run Code Online (Sandbox Code Playgroud)

这使观察者开始。第一个参数是观察者将监视其更改的节点。第二个参数是要注意什么选项。在childList添加或删除我想看子元素的手段。该subtree是修改扩展childList观看更改此元素的子树的任何地方(否则就只是看变化直接内<body>)。另外两个重要的可能性是attributescharacterData,这意味着对他们的声音是什么样子。

function callback(records) {
  records.forEach(function (record) {
Run Code Online (Sandbox Code Playgroud)

回调内部有些棘手。回调接收一个MutationRecord数组。每个MutationRecord可以描述一种类型的几个变化(childListattributes,或characterData)。由于我只告诉观察者注意childList,所以我不会费心检查类型。

var list = record.addedNodes;
Run Code Online (Sandbox Code Playgroud)

在这里,我抓取了所有添加的所有子节点的NodeList。对于未添加节点的所有记录,该字段将为空(并且可能会有很多此类记录)。

从那里开始,我遍历添加的节点并找到任何<select>元素。

这里没有什么复杂的。

jQuery的

...但是您要求使用jQuery。精细。

var observer = new MutationObserver(callback);
Run Code Online (Sandbox Code Playgroud)

这将domNodeInserted使用jQuery特殊事件API创建一个名为的新事件。您可以这样使用它:

$(document).on("domNodeInserted", "select", function () {
  $(this).combobox();
});
Run Code Online (Sandbox Code Playgroud)

我个人建议寻找一个类,因为某些库将创建select用于测试目的的元素。

自然,您还可以.off("domNodeInserted", ...)通过传递如下数据来使用或微调观看:

$(document.body).on("domNodeInserted", "select.test", {
  attributes: true,
  subtree: false
}, function () {
  $(this).combobox();
});
Run Code Online (Sandbox Code Playgroud)

select.test每当直接在主体内部更改元素的属性时,这将触发检查元素的外观。

您可以在下面或jsFiddle上看到它。

observer.observe(targetNode, { childList: true, subtree: true });
Run Code Online (Sandbox Code Playgroud)
function callback(records) {
  records.forEach(function (record) {
Run Code Online (Sandbox Code Playgroud)


注意

此jQuery代码是一个相当基本的实现。在其他地方进行的修改使您的选择器有效的情况下,它不会触发。

例如,假设您的选择器为.test select并且文档已经有一个<select>。添加类test,以<body>将选择有效的,但因为我只检查record.targetrecord.addedNodes,该事件将不会触发。您必须自行选择要更改的元素。

每当发生突变时,都可以通过查询选择器来避免这种情况。我选择不这样做,以避免对已处理的元素造成重复的事件。适当地处理相邻通用的同级组合器会使事情变得更加棘手。

有关更全面的解决方案,请参见https://github.com/pie6k/jquery.initialize,如DamienÓCeallaigh答案中所述


Die*_*itz 7

刚刚想出了解决我所有ajax问题的解决方案.

对于准备好的事件,我现在使用这个:

function loaded(selector, callback){
    //trigger after page load.
    $(function () {
        callback($(selector));
    });
    //trigger after page update eg ajax event or jquery insert.
    $(document).on('DOMNodeInserted', selector, function () {
        callback($(this));
    });
}

loaded('.foo', function(el){
    //some action
    el.css('background', 'black');
});
Run Code Online (Sandbox Code Playgroud)

对于正常的触发事件,我现在使用:

$(document).on('click', '.foo', function () {
    //some action
    $(this).css('background', 'pink');
});
Run Code Online (Sandbox Code Playgroud)


Dam*_*igh 6

有一个插件,adampietrasiak/jquery.initialize,它基于MutationObserver它简单地实现了这一点。

$.initialize(".some-element", function() {
    $(this).css("color", "blue");
});
Run Code Online (Sandbox Code Playgroud)


bip*_*pen 0

创建一个<select>id ,将其附加到文档..并调用.combobox

  var dynamicScript='<select id="selectid"><option value="1">...</option>.....</select>'
  $('body').append(dynamicScript); //append this to the place your wanted.
  $('#selectid').combobox();  //get the id and add .combobox();
Run Code Online (Sandbox Code Playgroud)

这应该可以解决问题..如果需要,您可以隐藏选择,然后.combobox显示它..或者使用查找..

 $(document).find('select').combobox() //though this is not good performancewise
Run Code Online (Sandbox Code Playgroud)