Javascript授权最佳实践
我现在正在开发/已经开发了一些系统,我在编程中遇到了一个问题,我似乎将我的JQuery函数委托给文档,如下所示:Javascript授权最佳实践,javascript,jquery,delegation,Javascript,Jquery,Delegation,我现在正在开发/已经开发了一些系统,我在编程中遇到了一个问题,我似乎将我的JQuery函数委托给文档,如下所示: $(document).on('click', '.modal-editor', function () { //code }); $(document).on('click', '.another-class', function () { //code }); $(document).on('click', '#another-id', function ()
$(document).on('click', '.modal-editor', function () {
//code
});
$(document).on('click', '.another-class', function () {
//code
});
$(document).on('click', '#another-id', function () {
//code
});
这有什么问题吗
更新:
好的,所以本质上这没有问题,直到:
回到我的问题(最佳实践),最佳实践是尽可能将事件委托给最近的静态元素,以避免上述情况。您的代码没有问题
$(document)
不必始终放置在事件委派中,该选择器引用动态添加元素的最近父元素:
语法:
$(closest parent selector).on('event','target selector', function(){
});
您也可以使用document.body
$(document.body).on('event','target selecor',function(){
});
旁注:对于现有的DOM元素,可以使用普通的单击事件
$('selector').click(function(){
});
或
$('selector').on('click',function(){
});
有关更多信息,请参阅API文档。当您希望将特定事件应用于多个元素,而每个元素都没有自己的事件处理程序时,委托非常有用。在上面的例子中,前两种方法可能会出现这种情况 在理论上只有一个元素与标准匹配的情况下,根据文档的大小,可能会产生性能影响,因为每个事件都必须根据处理程序过滤器进行测试,以查看是否匹配 此外,如果每个方法都作为委托添加,并且您经常加载和上载页面的部分,那么这些事件将比它们所属的页面上的元素停留的时间更长 您可以将处理程序委托给document元素以外的其他元素,例如周围的
div
,或者在这种情况下可以委托给其他元素。或者使用事件名称空间来确保没有多次添加事件
“这有什么问题吗?”
对。发生的每个事件都需要针对e.target
和文档之间的每个元素运行每个选择器。那太贵了
基本上就像这个简化的伪代码:
// start on the e.target
var node = e.target;
// For the target and all its ancestors until the bound element...
while (node && node !== this) {
// ...test the current node against every click selector it was given
for (var i = 0; i < click_selectors.length; i++) {
// If a selector matches...
if ($(node).is(selector)) {
// ...run the handler for that selector
}
}
node = node.parentNode;
}
//从e.target开始
var节点=e.target;
//对于目标及其所有祖先,直到绑定元素。。。
while(节点和节点!==此){
//…根据给定的每个单击选择器测试当前节点
对于(变量i=0;i<单击_selectors.length;i++){
//如果选择器匹配。。。
if($(节点).is(选择器)){
//…运行该选择器的处理程序
}
}
node=node.parentNode;
}
此外,如果您的代码或加载的其他代码在e.target
和文档之间绑定了一个处理程序,并调用e.stopPropagation()
,则事件将永远不会到达文档,因此您的事件将不会触发
最好让您的委派尽可能接近预期的元素。并且主要用于动态加载的元素,因为它增加了额外的开销,特别是在快速触发事件的情况下。是的。实际上,它本身并不存在,但从文档(DOM的根)中委派所有事件确实意味着所有单击事件,包括您不感兴趣的事件,将至少部分地得到处理:
$(document).on('click', '$another-id', function(){});
在这方面,这是一个特别糟糕的主意:你只关注一个元素,但是如果我点击身体的任何地方,jQ会做如下事情:
if (event.target.id == 'another-id')
{
return callback.call(event.target, $(event));//where callback is the anonymous function you passed to on
}
return event;
因此,所有单击事件都会导致函数调用。这会降低您的UI速度。
你决不能停止委派事件,而是要明智地约束听众。例如,如果要使用的所有DOM元素都包含在#container
div中,则将侦听器绑定到该容器中。如果要处理导航事件,请将侦听器绑定到包含所有导航元素的节点
此外,如果您取消了一个事件,但未能停止ProPagation,那么该事件仍将调用可能排队的所有其他侦听器。Returnignfalse
也会引起问题,因为在jQ中,return false
被翻译为e.preventDefault();e、 stopPropagation()
。因此,在处理嵌套元素时要小心,如果要处理页面中的链接,也要处理
等元素,则可能会调用这两个处理程序,具体取决于使用的选择器:
$(document).on('click', 'a', function(){});//is called for all links
$(document).on('click', 'a.navigation', function(){});//is called for navigation
哪个将首先被调用?在特定情况下,您希望使用哪一种?这里有错误的空间,这不应该存在:
$('#navContainer').on('click', 'a.navigation', function(){});//is called for all links
至少让事情变得更安全、更清晰、更轻松
如果要使用ID选择器委派事件,且该元素已存在于DOM中,请不要委派:
它比较短,而且无论如何可能会更快我不这么认为。。。你应该很好…这可能会成为一个大规模的问题;没有全面的答案。关于你的更新,不,我不会等待出现性能问题。jQuery出于某种原因放弃了.live()
方法。对于明智的实践,即使它们目前没有明显的好处,也有一些值得一提的地方。@cookiemonster-jQuery放弃了live()
方法,因为它的功能太具体了。jQueryAPI倾向于使用同一方法执行多项操作,具体取决于您提供的参数。您可以使用on()
或delegate执行与live()相同的功能
$('#another-id').on('click', function(){});