I've seen a lot of different questions similar to this, but all of them generally targeted a specific selector. Please let me know if there is a duplicate somewhere and I've missed it.
我见过很多类似的问题,但它们都针对特定的选择器。请告诉我是否有副本,我错过了。
Take this scenario:
把这个场景:
You want to build a jquery plugin for a wordpress, drupal, or basically any site that uses third party functionality. Since you don't know ahead of time every specific event and selector you will need to target how would you add jquery/javascript functionality to elements that are created dynamically. Plus you don't know how the element is created (callback using ajax/php/etc).
您希望为wordpress、drupal或任何使用第三方功能的站点构建jquery插件。由于您不提前知道每个特定的事件和选择器,所以您需要针对如何向动态创建的元素添加jquery/javascript功能。另外,您不知道如何创建元素(使用ajax/php/等等进行回调)。
Example:
例子:
I recently tried adding select2 or selectize to my entire site. Unfortunately, since I can't determine ahead of time when select elements (from other plugins/modules) will be added, I can't ensure that the select jquery will work on newly created selects.
我最近尝试在整个站点中添加select2或selectize。不幸的是,由于我无法提前确定何时会添加select元素(来自其他插件/模块),我无法确保选择jquery对新创建的select起作用。
Select2
Select2
This is the normal way but doesn't work on dynamically created or cloned selects:
这是通常的方法,但不用于动态创建或克隆选择:
<script type='text/javascript'>
jQuery(document).ready(function($) {
$("select").select2();
});
</script>
If I knew all the events that added these selects I could simply do the following:
如果我知道所有添加这些选择的事件,我可以做以下事情:
$( ".some_button_that_creates_new_selects" ).on( "click", function() {
jQuery("select").select2();
});
});
However, since I don't know all the selectors of dynamic selects ahead of time (since many are added by 3rd party plugins), select2 will not work on new selects. So the above would only work on a per case senerio.
但是,由于我不知道动态选择器的所有选择器(因为许多选择器是由第三方插件添加的),所以select2不会在新的选择器上工作。所以上面的条件只适用于每种情况。
I need to find a way to traverse through the dom tree and recognize when new selects are created.
我需要找到一种方法来遍历dom树,并在创建新选择时识别。
I tried targeting several events with .on but it didn't work well at all.
我尝试过用.on来定位几个事件,但都没有成功。
I read that the javascript document.getElementsByTagName
recognizes changes in the dom and are reflected in the collection. I also looked into querySelectorAll
, but not sure exactly how it works.
我读取了javascript文档。getElementsByTagName识别dom中的更改,并反映在集合中。我还研究了querySelectorAll,但不确定它是如何工作的。
I also tried messing with the MutationObserver
and checking if the .addednodes.length
of select tags changed, but I didn't really get anywhere.
我还尝试过干扰MutationObserver并检查.addednode。选择标签的长度改变了,但是我没有得到任何结果。
UPDATE
更新
After doing some testing I realized that the problem might lie within the select2 plugin itself. Select2 loads dynamic selects but doesnt get the positioning. Chrome eventually throws typeerros : cannot read property 'find' of null, cannot read property 'hasclass' of null.
在做了一些测试之后,我意识到问题可能存在于select2插件本身。Select2加载动态选择,但没有获得位置。Chrome最终抛出typeerros:无法读取null属性'find',无法读取null属性'hasclass'。
2 个解决方案
#1
6
Solution:
I am going to answer your base question "Attach javscript/jquery event on dynamically created elements".
我将回答您的基本问题“在动态创建的元素上附加javscript/jquery事件”。
For adding event on dynamically created elements you have to take advantage or Event Delegation, when a event trigger on an element it propagates.
要在动态创建的元素上添加事件,您必须利用或事件委托,当事件触发它传播的元素时。
So if you attach event handler on a root element( it can be body or any parent element which is present when you are attaching this event)
因此,如果在根元素上附加事件处理程序(可以是body,也可以是在附加事件时出现的任何父元素)
$("body").on("click","elementSelector", function(){
});
Now this will capture event from dynamically created elements as well.
这也将从动态创建的元素中捕获事件。
#2
2
The easiest solution is to create a function in javascript which will be called everytime when you add any control dynamically on the page and in that function you can placed the check so event will be registered only on new components. e.g.
最简单的解决方案是在javascript中创建一个函数,每次在页面上动态添加任何控件时都将调用该函数,在该函数中可以放置check,以便仅在新组件上注册事件。如。
function registerEvents()
{
//Get all the select events from the page and register events only on those controls which are new ..
$("select").each(function() {
if (!$(this).hasClass("registeredEvent")) {
$(this).addClass("registeredEvent");
$(this).select2();
}
});
}
Same results can be achieved through different approaches..
同样的结果可以通过不同的方法得到。
Also check .live event in jquery .. it register events automatically when the new element is added with the same tag or class..
还可以用jquery查看.live事件。当使用相同的标记或类添加新元素时,它会自动注册事件。
#1
6
Solution:
I am going to answer your base question "Attach javscript/jquery event on dynamically created elements".
我将回答您的基本问题“在动态创建的元素上附加javscript/jquery事件”。
For adding event on dynamically created elements you have to take advantage or Event Delegation, when a event trigger on an element it propagates.
要在动态创建的元素上添加事件,您必须利用或事件委托,当事件触发它传播的元素时。
So if you attach event handler on a root element( it can be body or any parent element which is present when you are attaching this event)
因此,如果在根元素上附加事件处理程序(可以是body,也可以是在附加事件时出现的任何父元素)
$("body").on("click","elementSelector", function(){
});
Now this will capture event from dynamically created elements as well.
这也将从动态创建的元素中捕获事件。
#2
2
The easiest solution is to create a function in javascript which will be called everytime when you add any control dynamically on the page and in that function you can placed the check so event will be registered only on new components. e.g.
最简单的解决方案是在javascript中创建一个函数,每次在页面上动态添加任何控件时都将调用该函数,在该函数中可以放置check,以便仅在新组件上注册事件。如。
function registerEvents()
{
//Get all the select events from the page and register events only on those controls which are new ..
$("select").each(function() {
if (!$(this).hasClass("registeredEvent")) {
$(this).addClass("registeredEvent");
$(this).select2();
}
});
}
Same results can be achieved through different approaches..
同样的结果可以通过不同的方法得到。
Also check .live event in jquery .. it register events automatically when the new element is added with the same tag or class..
还可以用jquery查看.live事件。当使用相同的标记或类添加新元素时,它会自动注册事件。