jQuery.change + inline onchange fn()导致fn执行两次

时间:2010-10-02 17:40:10

标签: asp.net jquery internet-explorer-8

尽管我找到了答案并找到了解决办法,希望能帮到其他人。

基本上,当使用 IE8 并更改元素的值时, jQuery.change 会挂钩并且内联onchange 定义,< strong> onchange中的代码执行两次。

我们在 ASP.NET(3.5或4.0 无关紧要)项目中遇到了 jQuery 1.4.2 AutoPostBack = true 控件,使用onchange =“__ doPostBack(...)”属性进行渲染,导致回发在单个用户启动的控件状态更改时发生两次。 (微软真的需要退出浏览器业务 - 他们很糟糕。)

为了演示这个问题,我创建了一个空的网站项目并添加了一个aspx页面,下面是完整的代码+标记。重要的元素是对jQuery的SCRIPT引用,连接control.change处理程序的$ document.ready,以及单独的autopostback控件(我已经验证它与TextBox和DropDownList一起发生)。请注意,页面上不存在其他控件 - 没有AJAXToolkit控件,如UpdatePanels,也没有带有空SRC attribs的IMG,这是一个长期存在的错误,也会触发双回发。

<%@ Page Language="C#" AutoEventWireup="true" EnableEventValidation="false" 
    EnableSessionState="False" EnableViewState="false" %>

<script runat="server">
    protected void Page_Init(object sender, EventArgs e)
    {
        Trace.Write(String.Format("IsPostBack = {0}; PostbackControl = {1}",      
          IsPostBack.ToString(), Page.Request.Params.Get("__EVENTTARGET")));
    }

    protected void txtTest_TextChanged(object sender, EventArgs e)
    {
        Trace.Write(String.Format("Name = {0}", txtTest.Text));
    }
</script>

<html>
  <head>
    <title>Demo of jQuery + AutoPostBack double postback problem</title>
  </head>
  <body>
    <form id="Form1" runat="server">

      <script src="jquery-1.4.2.js" type="text/javascript"></script>
      <script type="text/javascript">
          $(document).ready(function () {
              $('#<%= txtTest.ClientID %>').change(function () { 
                alert('Double postback coming up!'); 
              })
          });
      </script>

      <asp:TextBox ID="txtTest" runat="server" AutoPostBack="true" 
        OnTextChanged="txtTest_TextChanged" />

    </form>
  </body>
</html>

您可以通过在Page_Init中设置断点,启用IE脚本调试并单步执行javascript以查看onchange执行两次,或者通过启用跟踪并在trace.axd中查看生成的两个请求来观察双回发。

你放在jQuery.change处理程序中的内容并不重要;删除警报或让它返回bool甚至使处理程序完全为空对double onchange / postback行为没有影响。

无论是在标记中还是在命令中以声明方式连接服务器端TextChanged事件处理程序,都会发生这种情况(显然你不应该同时执行这两种操作,或者你自己会导致双重回发)。

即使ASP.NET生成的onchange =“__ doPostBack(...)”正在执行两次,jQuery.change处理程序只执行一次因为警报只显示一次。偶尔(可能是5个或6个通道中的1个),onchange只会触发一次,回发一次,因此该错误似乎并不一致。

更糟糕的是,在我们第一次遇到此行为的实际生产项目中,有时当它发布双重帖子时,一个请求的IsPostBack = true而另一个请求为false,导致初始化代码再次执行。但是我无法在演示项目中重现这种行为,因此它可能是与此交互的单独问题。

如果您注释掉jQuery.change,它将恢复为正常的所需单个回发行为。

我用Google搜索过疯狂但只能找到 MIGHT 一直面临同一问题的论坛帖子。只有在我确定Firefox中没有出现问题并将IE8添加到我的搜索词列表中之后,才会遇到jQuery错误报告。 http://dev.jquery.com/ticket/6310 http://dev.jquery.com/ticket/6593

解决方法(在ASP.NET中)是禁用AutoPostBack并在jQuery事件处理程序的末尾为所有必须同时运行客户端和服务器端代码的控件显式添加__doPostBack。

编辑:修复了jQuery选择器,正如meep指出的那样,它缺少#。

2 个答案:

答案 0 :(得分:0)

据我所知,此问题仅限于Internet Explorer,因此,如果您有此选项,请将IE从您的应用用户中移除。

或者禁用AutoPostBack并在jQuery事件处理程序的末尾显式添加__doPostBack,以用于必须运行客户端和服务器端代码的所有控件。如果您使用的是普通的-html控件,请不要对相同的元素使用inline onchange和jQuery.change。

或者自己破解jQuery以防止在更改挂钩时执行两次onchange。

或者等待jQuery的下一个版本,并希望问题得到解决。

微软可能永远无法解决问题,因为他们继续将旧的IE6漏洞传播到更新的IE版本。

答案 1 :(得分:0)

抛开微软的抨击,这比IE的更多是jQuery的错。它是由jQuery尝试解决IE中change事件缺少冒泡而导致的,除了自然更改事件之外,还为每个祖先元素以及目标元素调用额外的伪造change事件。据推测,这个错误没有引起注意,因为触发多个onchange事件通常是无害的。

(这不是答案。但是,你的问题不是问题。)