html重置后javascript事件丢失

时间:2011-08-09 15:16:17

标签: javascript jquery

我有一种情况,在某种程度上,div的html内容被更改为其他内容,然后被更改回来。一些jquery ui控件是行为不端的。我已将问题简化为以下代码段,它基本上显示与该按钮关联的事件处理程序不再触发。我假设当它们消失时,这些都是垃圾收集的。所以我的问题是 -

如何防止事件处理程序在DOM中丢失时被垃圾回收

我知道我可以重新分配click()函数,但由于我使用的是外部库(jquery ui),我真的不知道它对我的控件做了什么。我只是希望他们的活动恢复原状。

<div id="container">
    <p>This container has a button, which will forget its click()...</p>
    <input id="testbutton" type="button" value="Click Me!"/>
</div>

<script type="text/javascript">
    $(function(){ 
        $("#testbutton").click(
            function(){
                alert("Button has been clicked!");
        })
    });
</script>

<div>
    <p>... when this button reseats html</p>
    <input id="actionbutton" type="button" value="Toggle"/>
</div>

<script type="text/javascript">
    var toggle = false;
    var html;
    $(function(){ 
        $("#actionbutton").click(
            function(){
                toggle = !toggle;
                if(toggle){
                    html = $("#container").html();
                    $("#container").html("");
                } else  $("#container").html(html);
        })
    });
</script>

jfiddle演示了我遇到的问题。

4 个答案:

答案 0 :(得分:5)

简单回答:使用.live

$(function(){ 
    $("#testbutton").live('click',
        function(){
            alert("Button has been clicked!");
    })
});

这是更新的小提琴:http://jsfiddle.net/mrchief/8S5E4/1/

说明:当您更改DOM时,附加元素的事件处理程序也会被删除。使用.live将事件处理程序附加到“body”(并按DOM元素过滤),以便即使在删除/添加相同的DOM元素后它也“存在”。

使用.delegate也可以达到相同的效果:

$(function(){ 
    $('#container').delegate('#testbutton', 'click',
        function(){
            alert("Button has been clicked!");
    })
});

使用.delegatehttp://jsfiddle.net/mrchief/8S5E4/6/

我建议使用.delegate而不是.live

  • 您可以取消事件冒泡。当您使用live时,事件会一直冒泡到body,然后您的处理程序被调用,因此无法取消其冒泡。 (从jQuery 1.4开始,可以通过使用上下文参数来防止这种情况:http://api.jquery.com/live/
  • 由于你是专门附加到DOM元素的,所以每次点击身体上的任何其他DOM元素时都不会调用它,因此它的性能更高,因为它现在必须做更少的工作。

这是一篇精彩的文章,精美地解释了differences between live, delegate and bind,并讨论了每种方法的细微差别。感谢@andyb指出这个链接。

答案 1 :(得分:3)

jQuery事件委托给救援

$("#container").delegate('#testbutton', 'click',
    function(){
        alert("Button has been clicked!");
});

注意:.delegate() is more efficient.live()

答案 2 :(得分:3)

这种情况正在发生,因为您将事件绑定到#testbutton上的#container文件已准备就绪。当您清除#container的HTML时,您也会丢失#testbutton绑定点击事件。相反,click事件引用的元素不再存在。

如果您希望该按钮事件持续存在,请尝试使用live()绑定或delegate()来自父元素的事件。


使用live()

$(function(){ 
    $("#testbutton").live("click", function() {
        alert("Button has been clicked!");
    })
});
  

为现在和将来与当前选择器匹配的所有元素附加事件的处理程序。


使用delegate()

$(function(){ 
    $("#container").delegate("#testbutton", "click", function() {
        alert("Button has been clicked!");
    })
});
  

根据一组特定的根元素,为现在或将来与选择器匹配的所有元素的一个或多个事件附加一个处理程序。

答案 3 :(得分:2)

使用live()功能代替

jsFiddle