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都被调用,no。发送的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);
}
});
}
答案 0 :(得分: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');
});
}
OR,我个人宁愿推荐这种方式,因为除了其他方面它的开销较少,在初始化代码中只附加一次事件。你可以随时附加事件,在你的示例中在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()中关注它,就会触发事件。