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 リクエストの数が 1 増加します。依頼内容は同じようですが、理由がわかりません。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,
    }); 
}

これはロングポーリング Web ページです。sendMsg は、ツリーでユーザーが行った変更を送信し、応答は気にしません。もう 1 つの関数 waitForMsg は、ロング ポーリング ajax リクエストです。sendMsg による db の変更を確認すると、jstree() 関数を再度呼び出してツリーを再作成します。ツリーに変更を加えると、sendMsg は最初に 1 リクエスト、2 秒目に 2 リクエスト、3 度目に 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() 呼び出しごとに 1 ずつ増加します。

修正?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');
    }); 
}

または、特にオーバーヘッドが少ないため、個人的にはこの方法をお勧めします。初期化コードでイベントを 1 回だけアタッチします。いつでもイベントをアタッチできます。たとえば、例の 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 に答える