使用jQuery重新绑定事件不起作用。

7

我有一个针对演示布局的页面设置:

+------------------------+
|prev                next|
|+----------------------+|
||         page         ||
||   dynamic content    ||
||                      ||
|+----------------------+|
+------------------------+

在上面的示例中,next/prev是导航按钮,使用$("page").load(url);控制动态内容。
在其中一个页面上,我有一个弹出框,其中有按钮与ajax调用链接,它们控制弹出框的内容。
当页面首次加载时,这些按钮可以很好地完成其工作。如果更改页面(使用导航按钮)并再次更改回来,则弹出框将打开,但按钮不起作用。如果您单击按钮,关闭弹出窗口,然后重新打开弹出窗口,则会显示您在第一次单击时请求的信息,但按钮仍然无法正常工作。
这告诉我ajax请求没有问题,某处元素绑定存在问题。以下是我的Javascript代码:
$('#resTable').on('click',this,function() {
    $('#ayAvgDPm').html("");
    $('#aoAvgDPm').html("");
    $('#ayTotProfit').html("");
    $('#aoTotProfit').html("");
    $('#ayAvgPcPm').html("");
    $('#aoAvgPcPm').html("");
    $('#ayTotPcProfit').html("");
    $('#aoTotPcProfit').html("");
    $('#ayrRes').html("");
    $('#etfProductPopup').bPopup();
});

$('div[class^="sideNav"]').on('click',this,function() {

    $('#yrSummary').fadeIn(200);

    $('#yAvgDPm').html("");
    $('#oAvgDPm').html("");
    $('#yTotProfit').html("");
    $('#oTotProfit').html("");
    $('#yAvgPcPm').html("");
    $('#oAvgPcPm').html("");
    $('#yTotPcProfit').html("");
    $('#oTotPcProfit').html("");
    $('#yrRes').html("");

    var yr = "20"+$(this).attr('class').substr(-2);

    var req = $.ajax({
        url : '../includes/prod_results.php',
        type : 'POST',
        dataType : "json",
        data : {
            y : yr,
            t : 'ETF'
        },
        success : function(j) {
            var table = "<table cellspacing='0'><tr><th>Year</th><th>Returns</th></tr>";
            for(var i = 0; i < 12; i++) {
                if (i === 5 && yr === '2014'){
                    break;
                }
                var obj = j[i];
                var month = obj['month'];
                var profit = obj['profit'];
                var bal = obj['bal'];
                table += "<tr><td style='width:75px'>"+month+"</td><td style='padding: 0 15px'>"+parseFloat(profit).toFixed(2)+"%</td><td style='width:75px'>$"+comma(parseFloat(bal).toFixed(2))+"</td></tr>";
                if (i === (11)) {
                    table += "</table>";
                }
            }
            var YAvgDPm = comma(parseFloat(j.YAvgDPm).toFixed(2));
            var OAvgDPm = comma(parseFloat(j.OAvgDPm).toFixed(2));
            var YTotProfit = comma(parseFloat(j.YTotProfit).toFixed(2));
            var OTotProfit = comma(parseFloat(j.OTotProfit).toFixed(2));
            var YAvgPcPm = comma(parseFloat(j.YAvgPcPm).toFixed(2));
            var OAvgPcPm = comma(parseFloat(j.OAvgPcPm).toFixed(2));
            var YTotPcProfit = comma(parseFloat(j.YTotPcProfit).toFixed(2));
            var OTotPcProfit = comma(parseFloat(j.OTotPcProfit).toFixed(2));

            $('#yAvgDPm').html("$"+YAvgDPm);
            $('#oAvgDPm').html("$"+OAvgDPm);
            $('#yTotProfit').html("$"+YTotProfit);
            $('#oTotProfit').html("$"+OTotProfit);
            $('#yAvgPcPm').html(YAvgPcPm+"%");
            $('#oAvgPcPm').html(OAvgPcPm+"%");
            $('#yTotPcProfit').html(YTotPcProfit+"%");
            $('#oTotPcProfit').html(OTotPcProfit+"%");
            $('#yrRes').html(table);
            $('#yrGraph').html("<img src='../images/graphs/etf_"+yr+".jpg'>");
            return false;
        }
    });
    return false;
});

我知道这篇文章比较长...

我已经尝试过上面的脚本,无论是在$(document).ready()处理程序内还是外都试过了。

请问有人能帮我看看我做错了什么吗?

编辑说明:如请求所示,HTML:

<table id="resTable" cellspacing="0">
    <tr>
        <th>Year</th>
        <th> 1st Quarter</th>
        <th>2nd Quarter</th>
        <th>3rd Quarter</th>
        <th>4th Quarter</th>
        <th>Year Total</th>
        <th>Month Avg</th>
    </tr>
...
</table>

<div id="etfProductPopup">
<h1 style="text-align:center">ETF - Compounded Results</h1>
<div id="popupLeftBar">
    <div class="sideNav14">
        2014
    </div>
    <div class="sideNav13">
        2013
    </div>
    <div class="sideNav12">
        2012
    </div>
    <div class="sideNav11">
        2011
    </div>
    <div class="sideNav10">
        2010
    </div>
    <div class="sideNav09">
        2009
    </div>
    <div class="sideNav08">
        2008
    </div>
    <div class="sideNav07">
        2007
    </div>
    <div class="sideNav06">
        2006
    </div>
    <div class="sideNav05">
        2005
    </div>
    <div class="sideNav04">
        2004
    </div>
    <div class="sideNav03">
        2003
    </div>
</div>
<div id="popupMain">
    <div id="yrSummary">
        <table cellspacing="0">
            <tr>
                <th></th>
                <th>Avg<br>$/Mth</th>
                <th>Total<br>$ Profit</th>
                <th>Avg<br>%/Mth</th>
                <th>Total<br>% Profit</th>
            </tr>
            <tr>
                <th>Year</th>
                <td id="yAvgDPm"></td>
                <td id="yTotProfit"></td>
                <td id="yAvgPcPm"></td>
                <td id="yTotPcProfit"></td>
            </tr>
            <tr>
                <th>Overall</th>
                <td id="oAvgDPm"></td>
                <td id="oTotProfit"></td>
                <td id="oAvgPcPm"></td>
                <td id="oTotPcProfit"></td>
            </tr>
        </table>
    </div>
    <div id="yrGraph"></div>
    <div id="yrRes"></div>
</div>

真的吗?没有其他关于这个问题的想法吗?我真的需要你们在这件事上帮助我!

导航按钮的代码:

function nav(d) {
n = page + d;
$('#slide').load('p/'+n+'.php');

}

HTML:

<div class="prev" onClick="nav(-1)" title="Previous Page">&lt;&lt; Previous</div>
<div class="next" onClick="nav(1)" title="Next Page">Next &gt;&gt;</div>

编辑

我已经尝试了所有三个(当前的)答案,却毫无进展!这非常令人沮丧!

我开始觉得可能存在一些潜在问题,而绑定不是完整的问题。

显然需要像浏览器刷新一样加载页面。事实上,页面第一次加载时无论如何加载都能正常工作,这让我觉得绑定都没有问题。

没有弹出窗口时页面也能正常工作。

除了绑定,还有什么可能导致潜在问题的想法吗?

另外,我知道在SO上发布指向有问题的网页的链接是违反规则的,但如果有人想要一个链接,我会私下提供。请问一下。

编辑

所以,我在思考,隐藏的div(用于弹出窗口)即使在使用以下脚本后仍然保持填充状态:

$('#etfProductPopup').bPopup({
        onClose : function() {
            postLoadBindings();
            $('#ayAvgDPm').html("");
            $('#aoAvgDPm').html("");
            $('#ayTotProfit').html("");
            $('#aoTotProfit').html("");
            $('#ayAvgPcPm').html("");
            $('#aoAvgPcPm').html("");
            $('#ayTotPcProfit').html("");
            $('#aoTotPcProfit').html("");
            $('#ayrRes').html("");
        }
    });

我认为问题可能出现在弹出窗口脚本上... https://raw.githubusercontent.com/dinbror/bpopup/master/jquery.bpopup.min.js 另外我刚刚注意到,在页面加载时,弹出框div被重复了。从控制台可以看出:
<div id="etfProductPopup" style="display: none; left: 440px; position: absolute; top: 156px; z-index: 2147483650; opacity: 0;">...</div>

<div id="etfProductPopup" style="display: none; left: 440px; position: absolute; top: 156px; z-index: 2147483650; opacity: 0;">...</div>

编辑

是的,我意识到如果有一个“最多编辑自己问题”的徽章,那么我会赢得这个徽章,但我认为我提供的数据越多,就越有机会得到回应。

我在另一个页面上创建了一个#resTable元素(与之前加载方式相同)。我注意到,即使在文档准备好处理程序中使用$('#resTable').unbind(),单击该元素仍会弹出来自前一页的弹出窗口!

即使脚本甚至不存在于该页面,更不用说内容了,这是怎么可能的??

请问有人能帮我吗?这一定有一个合理的解释!我不是在试图编写人类,这是计算机代码,它运行着比特数据,不能像随心所欲地进行!

已经解决:弹出窗口在外部页面(具有导航按钮的页面)内创建了重复的div。我猜它是这样做的,以便它可以正确地层叠在整个页面上,而不仅是包含原始div代码的页面。

编辑

更深入地了解正在发生的事情。显然,弹出窗口的div在页面内,而不是在容器内。bPopup将该div移动到包含页面的<body>标签中。这意味着该div在bPopup调用后导航到的所有页面上都可用。关闭弹出窗口不会将div移回,因此当使用导航按钮重新加载页面时,该div被复制。

最新进展

与客户交谈后,我无法发布现场链接。创建jsFiddle需要很长时间。

如上所述,请注意,问题在于bPopup在父页面内重新创建了弹出窗口的div,并且在弹出窗口关闭时未将其删除。

我不确定是否有一种方法可以从页面中删除元素?问题在于,如果可以删除元素,则bpopup创建的副本与原始副本完全相同,因此任何针对副本的脚本也将针对原始副本。


@intracept已按要求添加了HTML。 - Wildcard27
你的导航按钮的代码是什么? - Jane S
@Lekshmi 我已经尝试过 async:false 但没有效果。而且我不记得说过我有关闭按钮的问题...? - Wildcard27
据我所知,在问题中添加链接并不违反规定,但不能只有链接,因为一旦链接失效,问题和答案就变得毫无价值。现在,请发布链接。如果您能创建一个包含可重现问题的简化测试用例的fiddle/jsbin/codepen或其他内容,那就更好了。有时候,创建简化测试用例可以让答案变得清晰明了。 - dc5
dc5 是正确的。尝试提供一个能够重现该问题的链接。 - ebiv
显示剩余18条评论
4个回答

1

@Sudhir提到的事件委托应该是可行的,但如果你遇到问题,你可以尝试在每次页面加载时强制绑定新的事件。类似这样的:

在具有“上一页”和“下一页”按钮的主页面中,定义所有函数 -

var bindEvents = function(){
    //we are unbinding to make 
    //sure we are not attaching more than once since
    //instead of on, I am using direct CLICK binding.
    $('#resTable').unbind("click").click(function() { 
        ....
    });

    $('div[class^="sideNav"]').unbind("click").click(function() {
        ....
    });
};

var nav = function(d) {
    n = page + d;
    $('#slide').empty();
    $('#slide').load('p/'+n+'.php', function(){
         //bind events
         bindEvents();
    });
}

$(function(){
    //the first page call, when page loads
    nav(0);
});

请记住,这不是最佳方法,但这能确保其他事情都是正常的。如果这个绑定工作了,那么我们就可以隔离问题并确认你使用绑定的方式有问题。如果还是不行,请告诉我。


1

我没有尝试过任何把戏,但你是否尝试将弹出按钮的事件绑定放在ajax请求的“complete”处理程序上?这似乎是一种更安全的方法,可以确保绑定到单个元素:

var req = $.ajax({
    url : '../includes/prod_results.php',
    type : 'POST',
    dataType : "json",
    data : {
        y : yr,
        t : 'ETF'
    },
    success : function(j) {
        var table = "<table cellspacing='0'><tr><th>Year</th><th>Returns</th></tr>";
        for(var i = 0; i < 12; i++) {
            if (i === 5 && yr === '2014'){
                break;
            }
            var obj = j[i];
            var month = obj['month'];
            var profit = obj['profit'];
            var bal = obj['bal'];
            table += "<tr><td style='width:75px'>"+month+"</td><td style='padding: 0 15px'>"+parseFloat(profit).toFixed(2)+"%</td><td style='width:75px'>$"+comma(parseFloat(bal).toFixed(2))+"</td></tr>";
            if (i === (11)) {
                table += "</table>";
            }
        }
        var YAvgDPm = comma(parseFloat(j.YAvgDPm).toFixed(2));
        var OAvgDPm = comma(parseFloat(j.OAvgDPm).toFixed(2));
        var YTotProfit = comma(parseFloat(j.YTotProfit).toFixed(2));
        var OTotProfit = comma(parseFloat(j.OTotProfit).toFixed(2));
        var YAvgPcPm = comma(parseFloat(j.YAvgPcPm).toFixed(2));
        var OAvgPcPm = comma(parseFloat(j.OAvgPcPm).toFixed(2));
        var YTotPcProfit = comma(parseFloat(j.YTotPcProfit).toFixed(2));
        var OTotPcProfit = comma(parseFloat(j.OTotPcProfit).toFixed(2));

        $('#yAvgDPm').html("$"+YAvgDPm);
        $('#oAvgDPm').html("$"+OAvgDPm);
        $('#yTotProfit').html("$"+YTotProfit);
        $('#oTotProfit').html("$"+OTotProfit);
        $('#yAvgPcPm').html(YAvgPcPm+"%");
        $('#oAvgPcPm').html(OAvgPcPm+"%");
        $('#yTotPcProfit').html(YTotPcProfit+"%");
        $('#oTotPcProfit').html(OTotPcProfit+"%");
        $('#yrRes').html(table);
        $('#yrGraph').html("<img src='../images/graphs/etf_"+yr+".jpg'>");
        return false;
    }, 
    complete:function(){
        //put the bindings to popup here
    }
});

1

更改:

$('#resTable').on('click',this,function() {
...

$(document).on('click','#resTable',function() {
...

并且

$('div[class^="sideNav"]').on('click',this,function() {
...

$(document).on('click','div[class^="sideNav"]',function() {
...

你认为它们放在$(document).ready()处理程序中和不放会有很大的区别吗?或者甚至放在外部页面而不是动态页面中? - Wildcard27
如果将其放置在 .ready() 处理程序中,则会产生不同的效果,正确的方式是将其放置在 .ready() 处理程序内部。 - Sudhir Bastakoti
那正是我想的。它大部分时间都在那里度过了,而且它就应该待在那里 :) - Wildcard27
它类似于已弃用的$.live(),因此可以放置在任何地方,因为您绑定到$(document)。 - Jacek Pietal

0

试一下这个

$("body").delegate('#resTable','click',function() {
    //some codes
}


$("body").delegate('div[class^="sideNav"]','click',function() {
    //some codes
}

Delegate()已被on()所取代。然而,我已经尝试过delegate()、live()和on()。 - Wildcard27

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接