为什么会这样?
- 采用带有单个 UpdatePanel 和 Button 的普通 ASP.NET Web 窗体。
- 在 ASP.NET 客户端 pageLoad 事件便利函数中(如果您愿意,可以使用 jQuery DOM)将表单元素包装在使用 jQuery 新创建的 div 元素中。
- 单击该按钮并注意发送了两个异步 (xhr) 回发(使用 F12 浏览器开发人员工具中的 Net 选项卡查看它们)。
这是一些重现该问题的示例代码:
<%@ Language="C#" %>
<!DOCTYPE html>
<html>
<head><title>Double async postback when form element wrapped in new div after page load</title></head>
<body>
<form id="frmTest" runat="server">
<asp:ScriptManager ID="smTest" runat="server" ScriptMode="Release" />
<asp:UpdatePanel ID="upTest" runat="server">
<ContentTemplate>
<asp:Button ID="btnTest" runat="server" Text="Test Postback"/>
</ContentTemplate>
</asp:UpdatePanel>
</form>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
function pageLoad() {
// jQuery:
$("<div></div>").insertBefore("form").append($("form"));
// DOM-only:
//document.body.insertBefore(document.createElement("div"), document.forms[0]).appendChild(document.forms[0]);
}
</script>
</body>
</html>
(我使用的是针对 .NET Framework 4.5.2 和 jQuery 1.7.1 的普通 web.config 文件。我能够在 Firefox 40.0.3、Chrome 45.0.2454.85 和 IE 11 中重现这一点。)
现在请注意,如果您注释掉 jQuery 行并取消注释 DOM-only 行,则只会发送一个回发。
此外,如果您在页面加载之前将表单标签包装在 div 中(即在静态 HTML 中)它可以正常工作(没有双重回发。)
为什么这很重要/我为什么在乎?许多 jQuery 插件(例如jPanelMenu)将 body 标签的全部内容(或大部分)包装在一个 div 中,以确保一个相对定位的祖先。