简体   繁体   English

附加和重新附加事件处理程序

[英]Attaching and reattaching Event Handlers

Im using event handlers from a framework (prototype to be specific) to attach listerners to certain elements of a page like this: 我使用框架(特定于原型)中的事件处理程序将侦听器附加到页面的某些元素,如下所示:

//html
<a href="?default=1" class="default">Set Default</a>
//js
document.observe('dom:loaded', function(){
        //get all elements with d 'default' classname
        for(i = 0;i < document.getElementsByClassName('default').length;i++)
        {
                s = document.getElementsByClassName('default')[i];
                //attach an onclick event
                s.observe('click', function(e){
                        //prevent the default action (i.e loading the page)
                        e.preventDefault();
                        //read d link attribute
                        ref = this.readAttribute('href');
                        //and now, do it the ajax way
                        new Ajax.Request('js/ajax/handler.php'+ref, {
                                method:'get',
                                onSuccess:function(transport){}
                        });
                });
        }
});

It works well. 它运作良好。 Really well. 真的很好 But there is a challenge. 但是,这是一个挑战。 Most times, such actions manipulates the DOM and may add one or more of the 'default' class element (ie another Set Default somewhere). 大多数情况下,此类操作会操纵DOM,并可能添加一个或多个“默认”类元素(即,在某处添加另一个“默认设置”)。 That is intentional actually. 这实际上是故意的。 But then, the newly added 'default' class element will not have the click event attached. 但是,新添加的“默认”类元素将不会附加click事件。 The shitty work around at the moment is to loop through all the 'default' classes again and re-attach the events. 目前,最糟糕的解决方法是再次遍历所有“默认”类并重新附加事件。 Any other ideas? 还有其他想法吗?

The usual way to solve that is via event delegation. 解决此问题的通常方法是通过事件委托。 If you hook the click event on a container that holds all of these .default items, you can respond in that one handler: 如果将click事件挂接到包含所有这些.default项的容器上,则可以在该处理程序中进行响应:

document.observe('click', function(event) {
    var elm;

    elm = event.findElement('.default');
    if (elm) {
        // do your nifty stuff with the element
    }
});

It doesn't have to be document if they share some higher-up container. 如果它们共享一些较高层的容器,则不必是document Docs for Event#findElement are here . Event#findElement文档在此处

BTW, there's a big performance problem with your for loop. 顺便说一句,for循环存在很大的性能问题。 You're calling document.getElementsByClassName on every iteration! 您每次迭代都在调用document.getElementsByClassName If you use event delegation, that loop goes away anyway, but if that doesn't work for whatever reason, call it once and then loop through the result: 如果您使用事件委托,则无论如何该循环都会消失,但是如果由于某种原因该循环不起作用,请调用一次 ,然后循环遍历结果:

var defaults = document.getElementsByClassName('default');
for (i = 0; i < defaults.length; i++)

您可以侦听页面上的所有click事件,然后使用事件的目标确定用户是否单击了className为“ default”的元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM