好的,让我们举一个简单的例子来展示它是如何工作的。
我们将在表单上放置一个简单的按钮,然后弹出一个
询问您是或否的对话框。
所以,第一个例子,阻塞代码(停止代码)。
这个例子行得通,因为叫做 HALTS 的 js 等待输入,然后返回 true 或 false。
我们有这个按钮+标记:
<asp:Button ID="cmdDelete" runat="server" Text="Delete Record" Width="112px" CssClass="btn"
OnClick="cmdDelete_Click"
OnClientClick="return mydelprompt()"
/>
<script>
function mydelprompt() {
return confirm("Delete record? ok")
}
</script>
因此,当我们在上面运行时,我们为 OnCientClick 事件返回 true 或 false 值。如果我们返回 true,那么服务器端按钮(和回发)将运行。
我们的服务器端代码(在回发时运行)是这样的:
protected void cmdDelete_Click(object sender, EventArgs e)
{
Debug.Print("Server delete code will run");
// server side code here to delete record
}
所以,如果我们点击确定,那么将发生回发(我们的按钮代码服务器端运行)。
因此,如果我们点击取消,则返回 false,因此不会发生回发,并且服务器端代码不会运行。
好的,现在让我们用 ajax 调用或简单的 jquery.UI 对话框替换上面的确认。 (两者确实是同一个问题)。
我们现在有这个代码:
<script>
function mydelprompt2(btn) {
var mydiv = $("#mydeldiv")
mydiv.dialog({
modal: true, appendTo: "form",
title: "delete", closeText: "",
width: "20%",
position: { my: 'left top', at: 'right bottom', of: btn },
buttons: {
Ok: (function () {
mydiv.dialog("close")
return true
}),
Cancel: (function () {
mydiv.dialog("close")
return false
})
}
});
return false;
}
</script>
那么,上述方法是否可行?
不!
为什么?
当我们点击我们的按钮时,上面的脚本会运行,但是是异步的——它直接运行,没有任何暂停或等待代码,所以上面脚本的最后一行将返回 false,而我们的回发不会发生,而且永远不会发生!!!
里面的代码
buttons: {
Ok: (function () {
mydiv.dialog("close")
return true
}),
Cancel: (function () {
mydiv.dialog("close")
return false
})
}
不相关,因为那些是回调。代码将运行,显示对话框,并且还返回 false 到按钮单击,因此不会运行。
我们现在将看到:
但是,例程已经返回 false - 脚本的最后一行。
当我们点击 ok 或 cancel 时,这些存根中的任何一个都可以运行 - 但我们已经向服务器端按钮返回 false - 它不会运行,我们的 ok/cancel 什么也不做。
那么,这里的解决方案是什么?
如上所述,由于这个js代码是异步的,所以它不能等待。
我经常使用两种解决方案。
一个技巧,是我在实际按钮下方创建一个隐藏按钮,将其隐藏,然后单击它。所以我会有这个:
<asp:Button ID="cmdDelete" runat="server" Text="Delete Record" Width="112px" CssClass="btn"
OnClick="cmdDelete_Click"
OnClientClick="return mydelprompt2(this)"
/>
<asp:Button ID="cmdDeleteH" runat="server" Text="Delete Record" Width="112px" CssClass="btn"
OnClick="cmdDelete_Click"
Style="display:none"
ClientIDMode="Static"
/>
所以,第二个按钮被隐藏了,现在我们的代码是这样的:
function mydelprompt2(btn) {
var mydiv = $("#mydeldiv")
mydiv.dialog({
modal: true, appendTo: "form",
title: "delete", closeText: "",
width: "20%",
position: { my: 'left top', at: 'right bottom', of: btn },
buttons: {
Ok: (function () {
mydiv.dialog("close")
$("#cmdDeleteH").click()
}),
Cancel: (function () {
mydiv.dialog("close")
})
}
});
return false;
}
</script>
所以,现在如果我点击确定,然后我点击第二个隐藏按钮来运行我们的代码。
这并不是那么糟糕,但我通常不喜欢添加第二个假隐藏按钮并单击。但是,以上方法现在确实有效。
如果你点击 ok,那么 post-back + 按钮代码就可以工作了。
如果你点击取消,那么 post-back + 按钮代码不起作用
我们实际上并不使用第一个按钮。
但是,还有另一种方法!
我现在经常使用这个代码,只需一个按钮。
<script>
mydelpromptok = false
function mydelprompt2(btn) {
if (mydelpromptok) {
mydelpromptok = false
return true
}
var mydiv = $("#mydeldiv")
mydiv.dialog({
modal: true, appendTo: "form",
title: "delete", closeText: "",
width: "20%",
position: { my: 'left top', at: 'right bottom', of: btn },
buttons: {
Ok: (function () {
mydiv.dialog("close")
mydelpromptok = true
btn.click()
}),
Cancel: (function () {
mydiv.dialog("close")
})
}
});
return false;
}
</script>
所以请注意我们在这里做什么。
用户点击按钮。 js(客户端代码)运行,弹出对话框(或进行 ajax 调用,然后按说明运行到代码末尾并返回 false。
所以,这意味着服务器端代码按钮不能运行,没有运行,也不会运行。
现在,当 ajax 调用完成,返回(或者在这种情况下你回答对话框),然后我们做这个技巧:
Ok: (function () {
mydiv.dialog("close")
mydelpromptok = true
btn.click()
所以我们设置全局 var = true。现在重新启动服务器侧按钮!
无论如何我都必须传递按钮,因为我希望通过使用此处的 jQuery 位置,按钮显示在按钮单击的正下方(和右侧)。
那么,现在会发生什么? btn.click() 触发按钮,然后按钮再次调用我们的 SAME 例程,但这一次发生了:
mydelpromptok = false
function mydelprompt2(btn) {
if (mydelpromptok) {
mydelpromptok = false
return true
}
所以,现在再次调用 SAME 例程 (btn.click()),但是由于我们设置了全局 var = true,所以例程在开始时会检查这个值,因为它是 true,所以我们返回那个值,服务器端按钮代码现在运行。
(请注意,mydelpromptok = false 仅在页面加载和变量的第一次初始化时运行 - 不是稍后,也不是每次调用代码时)。
因此,您的代码可以使用相同的想法。
当您从 ajax 调用返回时,设置您的 flag = true,然后使用 jQuery.Click() 方法再次“click()”该事件。它当然会触发例程再次运行,这一次返回 true,因此您的服务器端按钮将在 ajax 调用之后运行 - 即使 ajax 调用说需要 1-2 秒,代码也是如此等待,因为第一次调用 js 代码确实运行,不会停止(像大多数 js 代码一样 - 罕见的例外是我的第一个 confirm() 示例,但那和 alert() 是唯一真正停止 js 代码的两件事.
因此,大多数例程 - 包括 ajax 调用都不会停止代码。您调用的该例程将一直运行到该例程的末尾并退出。 ajax 调用完成后,成功代码存根现在将重新输入,并重新运行。那时你必须调用服务器端代码。如前所述,您可以使用假按钮、_doPostback() js 命令来执行此操作,或者执行我上面所做的操作。使用点击方式。
因为在 10 次中有 9 次中,我们希望按钮或单击事件返回 true/false,所以再次触发 click 事件时几乎没有什么坏处,但这次我们返回 true,并且同一例程的其余部分没有再次运行。
您可以通过考虑在 js 中使用“promise”来编写更流畅的代码,但是您最终会得到至少两个独立的例程,并且您仍然必须找到一种方法来触发/调用该点击事件。其他方法涉及“取消事件”或停止按钮的传播 - 但使用起来可能会很麻烦。
所以,要么额外隐藏按钮 - 并在 ajax 成功运行时单击它,要么坚持一个简单的事件,并引入该真/假标志。
我发现要向现有的 asp.net 按钮和单击事件添加确认/是/否对话框,上述方法效果很好,因为按钮代码和原始按钮事件需要零更改,除了添加客户端点击事件,以及返回真/假。
试试上面的想法。
但是,通过非阻塞代码,我的意思是那些 js 例程不会停止,但可以正常运行,它们被视为异步代码。
所以在您的示例代码中,您需要将最后一行返回 false,以便按钮单击不会运行。您必须再次单击,如果您希望帖子重新运行,则在例程开始时返回 true 并退出。除非我们单击按钮或再次触发该事件,否则您设置 true/false 的代码没有任何价值,因为在第一次单击时 - 您拥有的 js 例程不会停止,也不会等待 - 它一直运行到最后,并且为服务器端按钮/单击事件返回 true/false 为时已晚。