Публикация этого, хотя я нашел ответ и обходной путь, в надежде, что это поможет кому-то еще.
По сути, при использовании IE8 и изменении значения элемента, к которому подключен как jQuery.change, так и определенный встроенный 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; удаление предупреждения или его возвращение логического значения или даже полное опустошение обработчика не влияет на двойное поведение onchange/postback.
Это также происходит независимо от того, подключаете ли вы обработчик событий TextChanged на стороне сервера декларативно в разметке или императивно в коде (очевидно, вы не должны делать и то, и другое, иначе вы сами вызовете двойную обратную передачу).
Несмотря на то, что сгенерированный ASP.NET onchange="__doPostBack(...)" выполняется дважды, обработчик jQuery.change выполняется только один раз, поскольку предупреждение отображается только один раз. Иногда (может быть, 1 из 5 или 6 проходов) onchange срабатывает только один раз, отправляя обратно один раз, поэтому ошибка не проявляется постоянно.
Хуже того, в реальном производственном проекте, где мы впервые столкнулись с таким поведением, иногда при двойной публикации IsPostBack=true для одного запроса и false для другого, что приводит к повторному выполнению кода инициализации. Но мне не удалось воспроизвести это поведение в демонстрационном проекте, поэтому взаимодействие с этим может быть отдельной проблемой.
Если вы закомментируете jQuery.change, он вернется к нормальному желаемому поведению одиночной обратной передачи.
Я гуглил как сумасшедший, но смог найти только одно сообщение на форуме, которое МОГУТ столкнуться с той же проблемой. Только после того, как я определил, что проблема не возникает в Firefox, и добавил IE8 в список условий поиска, я наткнулся на отчеты об ошибках jQuery. http://dev.jquery.com/ticket/6310 http://dev.jquery. ком/билет/6593
Обходной путь (в ASP.NET) заключается в отключении AutoPostBack и явном добавлении __doPostBack в конце обработчиков событий jQuery для всех элементов управления, которые должны выполнять как клиентский, так и серверный код.
РЕДАКТИРОВАТЬ: исправлен селектор jQuery, в котором, как указал мип, отсутствовал #.