HTML重置后Javascript事件丢失

javascript event missing after html reset

本文关键字:事件 Javascript HTML      更新时间:2023-09-26

我遇到过这样的情况:在某一时刻,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>

简单回答:使用.live

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

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

解释:当你改变DOM,事件处理程序附加的元素也被删除。使用.live将事件处理程序附加到"主体"(和DOM元素过滤器),使其"生存",即使在删除/添加相同的DOM元素后。

您也可以使用.delegate实现相同的效果:

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

使用.delegate: http://jsfiddle.net/mrchief/8S5E4/6/

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

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

这是一篇很棒的文章,它漂亮地解释了live、delegate和bind之间的区别,并讨论了每种方法的细微差别。感谢@andyb指出这个链接

jQuery事件委托救援

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

注意:.delegate().live()更有效

发生这种情况是因为您将事件绑定到#testbutton,该事件位于文档准备好的#container内部。当你清除#container的HTML时,你也失去了#testbutton绑定的点击事件。相反,click事件引用的元素不再存在。

如果你想要按钮事件持续使用live()绑定或delegate()从父元素的事件。


使用活()

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

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


使用委托()

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

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

使用live()函数代替点击

jsFiddle

不支持使用live()。使用on(),如果有必要,在document级别使用它:

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

通过使用$(document),再生#testbutton的事件处理程序仍然是完整的。