Публикувах това, въпреки че намерих отговора и заобиколното решение, с надеждата, че ще помогне на някой друг.
По принцип, когато използвате IE8 и променяте стойността на елемент, който има едновременно jQuery.change закачен към него и дефиниран inline onchange, кодът в onchange се изпълнява два пъти.
Сблъскахме се с това в ASP.NET (3.5 или 4.0 няма значение) проект с jQuery 1.4.2 и AutoPostBack=true контроли, които се изобразяват с атрибути onchange="__doPostBack(...)", което кара обратното изпращане да се случи два пъти за една инициирана от потребителя промяна на контролното състояние. (Microsoft наистина трябва да излезе от бизнеса с браузъри - те са ужасни в това.)
За да демонстрирам проблема, създадох празен проект за уебсайт и добавих една страница aspx, пълен код+маркиране по-долу. Важните елементи са SCRIPT препратката към jQuery, $document.ready, който свързва манипулатора control.change и самотната контрола за автоматично обратно изпращане (проверих, че това се случва както с TextBox, така и с DropDownList). Обърнете внимание, че на страницата не съществуват други контроли -- няма контроли на AJAXToolkit, като UpdatePanels, и няма IMG с празни SRC атрибути, което е дългогодишен бъг, който също задейства двойно обратно изпращане.
<%@ 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, или дори превръщането на манипулатора в напълно празен няма влияние върху поведението на двойната промяна/постбек.
Също така се случва, независимо дали свързвате обработчика на събития TextChanged от страна на сървъра декларативно в маркиране или императивно в код (очевидно не трябва да правите и двете или сами ще си причините двойното обратно изпращане).
Въпреки че генерираният от ASP.NET onchange="__doPostBack(...)" се изпълнява два пъти, манипулаторът jQuery.change се изпълнява само веднъж, защото предупреждението се показва само веднъж. От време на време (може би 1 от 5 или 6 преминавания), onchange се задейства само един път, публикувайки обратно веднъж, така че грешката не изглежда да се проявява постоянно.
Още по-лошо е, че в реалния производствен проект, където за първи път се сблъскахме с това поведение, понякога, когато то удвоява публикации, IsPostBack=true за една заявка и false за другата, карайки кода за инициализация да се изпълни отново. Но не успях да възпроизведа това поведение в демонстрационния проект, така че може да е отделен проблем при взаимодействие с този.
Ако коментирате jQuery.change, той се връща към нормалното желано поведение при единично обратно изпращане.
Търсих в Google като луд, но успях да намеря само една публикация във форума, която МОЖЕ да е изправена пред същия проблем. Едва след като установих, че проблемът не е възникнал във Firefox и добавих IE8 към моя списък с думи за търсене, срещнах докладите за грешки в jQuery. http://dev.jquery.com/ticket/6310 http://dev.jquery. com/ticket/6593
Заобиколното решение (в ASP.NET) е да деактивирате AutoPostBack и изрично да добавите __doPostBack в края на jQuery манипулаторите на събития за всички контроли, които трябва да изпълняват както клиентски, така и сървърен код.
РЕДАКТИРАНЕ: Поправен е селектора на jQuery, в който, както посочи meep, липсва #.