1
var json_string=$.parseJSON(document.getElementById("json_db").innerHTML);
$(function () 
{
    $("#folder_tree").jstree({ 
        contextmenu: {items: customMenu},
        "json_data" : {data:json_string},
        "plugins" : [ "themes", "json_data", "ui", "contextmenu" ],

    });
});
function customMenu(node)
{
    var items = { };
}



$('#folder_tree').delegate('a', 'contextmenu', function (e)
{

        idn = $(this).parent().attr("id");
        if(idn) pool_control(idn,e); //sendMsg(idn)

});

嗨,我在 jsTree 中得到了一些非常奇怪的东西。上面的代码显示了树的创建和委托右键单击事件。sendMsg(idn) 将 AJAX 请求发送到另一个页面。pool_control(idn,e) 使用该事件在单击的节点旁边显示一个表单。表单填写完毕后,它会调用 sendMsg。

当我直接在委托事件处理程序(而不是 pool_control)中调用 sendMsg 时,该脚本运行良好。但是,当我通过 pool_control 调用它时,会发生这种情况:每个 pool_control 都被调用,没有。发送的 Ajax 请求数加一。请求的内容似乎是相同的,但我不知道为什么没有。ajax 请求增加。当我直接调用 sendMsg 时,这不会发生。

发生了什么?我该如何解决?

pool_control 和 sendMsg:

function pool_control(id,ev)
{

    $("#pool_count").css("left",ev.pageX);
    $("#pool_count").css("top",ev.pageY);
    $("#pool_count").css("visibility","visible");
    $("#poolbutton").click(function()
    {
        $('#pool_count').css('visibility','hidden');    
        sendMsg(id);
    });
    $("#poolcancel").click(function()
    {
        $('#pool_count').css('visibility','hidden');
    }); 
}

function sendMsg(a,ev)
{

    $('#pool_count').css('visibility','hidden');    
    var factid = $("#factid").val();
    var floor = $("#floor").val();
    var ceiling = $("#ceiling").val();
    var pool_count = $('#poolsize').val();
    var userid = document.getElementById("userid").innerHTML;
    $.ajax(
    {
        type: "POST",
        url: "generator.php",
        data: {what:a,name:factid,author:userid,floor:floor,ceiling:ceiling,pool_count:pool_count},
        async: false,
        cache: false,
        timeout:50000,
    }); 
}

这是一个长轮询网页。sendMsg 在树中发送用户所做的更改,而不关心响应。另一个函数 waitForMsg 是长轮询 ajax 请求。当它看到由于 sendMsg 导致 db 发生变化时,它会再次调用 jstree() 函数来重新制作树。当我在树中进行更改时,sendMsg 第一次发送 1 个请求,第二次发送 2 个请求,第三次发送 3 个请求,依此类推。我很确定该功能没有任何问题,但在这里,以防万一

function waitForMsg()
{
    var lastupdate = document.getElementById("lastupdate").innerHTML;
    var msg;
    $.ajax({
        type: "POST",
        url: "oracle.php",
        data: {lastupdate:lastupdate},
        async: true,
        cache: false,
        timeout:20000,

        success: function(data)
        { 
            msg = data.split("@");
            document.getElementById("lastupdate").innerHTML=msg[0];
            document.getElementById("json_db").innerHTML=msg[1];
            initPage(); //a <body onready> function which creates the tree again                
            setTimeout('waitForMsg()', 200 );
        },
        error: function(XMLHttpRequest, textStatus, errorThrown){
                            setTimeout('waitForMsg()', 1000);

        }
    });
}
4

1 回答 1

0

由于事件在 jQuery 中的工作方式,每次使用 .click() 等函数附加事件时,事件都会“堆叠”到列表中,而不是替换。

通俗地说,以下代码:

    $("#poolbutton").click(function()
    {
        $('#pool_count').css('visibility','hidden');    
        sendMsg(id);
    });

当点击发生时不告诉 jQuery运行它,而是将它添加到触发点击时应该运行的事物列表中

也就是说,如果你多次附加事件,例如以如下方式:

    $("#poolbutton").click(function()
    {
        $('#pool_count').css('visibility','hidden');    
        sendMsg(id);
    });

    $("#poolbutton").click(function()
    {
        $('#pool_count').css('visibility','hidden');    
        sendMsg(id);
    });

    $("#poolbutton").click(function()
    {
        $('#pool_count').css('visibility','hidden');    
        sendMsg(id);
    });

结果将是(您猜对了)每次单击都会调用 sendMsg() 3 次,因为附加的每个事件都是独立处理的。

由于每次调用 pool_control 时都会附加新的单击事件,因此结果是 sendMsg() 调用的数量,因此 ajax 请求每调用一次 pool_control() 就会增加一个。

修复?在 pool_control() 中再次绑定之前取消绑定单击事件:

function pool_control(id,ev)
{

    $("#pool_count").css("left",ev.pageX);
    $("#pool_count").css("top",ev.pageY);
    $("#pool_count").css("visibility","visible");
    $("#poolbutton").unbind('click').click(function()
    {
        $('#pool_count').css('visibility','hidden');    
        sendMsg(id);
    });
    $("#poolcancel").unbind('click').click(function()
    {
        $('#pool_count').css('visibility','hidden');
    }); 
}

或者,我个人更愿意推荐这种方式,因为它的开销更小,在初始化代码中只附加一次事件。您可以随时附加事件,在您的示例中在 pool_control() 之外的 contextmenu 上调用委托之前附加它们是非常好的,例如:

var json_string=$.parseJSON(document.getElementById("json_db").innerHTML);
$(function () 
{
    $("#folder_tree").jstree({ 
        contextmenu: {items: customMenu},
        "json_data" : {data:json_string},
        "plugins" : [ "themes", "json_data", "ui", "contextmenu" ],

    });
});
function customMenu(node)
{
    var items = { };
}

$("#poolbutton").click(function()
{
    $('#pool_count').css('visibility','hidden');    
    sendMsg(id);
});
$("#poolcancel").click(function()
{
    $('#pool_count').css('visibility','hidden');
}); 

$('#folder_tree').delegate('a', 'contextmenu', function (e)
{

        idn = $(this).parent().attr("id");
        if(idn) pool_control(idn,e); //sendMsg(idn)

});

function pool_control(id,ev)
{
    $("#pool_count").css("left",ev.pageX);
    $("#pool_count").css("top",ev.pageY);
    $("#pool_count").css("visibility","visible");
}

此方法确保事件仅附加一次,只要您不破坏#pool_count,您就可以离开,只要发生点击,事件就会被触发,而无需在 pool_control() 中关心它。

于 2012-06-26T23:28:43.357 回答