jQuery.change + inline onchange fn () заставляет fn выполняться дважды - PullRequest
2 голосов
/ 02 октября 2010

Отправка этого сообщения, даже несмотря на то, что я нашел ответ и обходной путь, в надежде, что это поможет кому-то еще.

В основном, при использовании 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 выполнить дважды, либо включив трассировку и просмотрев полученные два запроса в трассировке.axd.

Неважно, что вы помещаете в обработчик jQuery.change;удаление оповещения или возвращение логического значения или даже полное опустошение обработчика не влияет на поведение двойного onchange / postback.

Это также происходит независимо от того, подключен ли обработчик событий TextChanged на стороне сервера декларативно в разметке.или обязательно в коде (очевидно, вы не должны делать и то, и другое, иначе вы бы сами вызвали двойной постбэк).

Даже если генерируемый ASP.NET onchange = "__ doPostBack (...)" выполняется дваждыобработчик jQuery.change выполняется только один раз, поскольку предупреждение отображается только один раз.Иногда (может быть, 1 из 5 или 6 проходов) onchange срабатывает только один раз, отправляя обратно один раз, так что ошибка не проявляется последовательно.

Еще хуже, в реальном производственном проекте, где мы впервые столкнулись с таким поведением, иногда, когда он дважды публикует сообщения, IsPostBack = true для одного запроса и false для другого, вызывая повторный запуск кода инициализации.Но я не смог воспроизвести это поведение в демонстрационном проекте, так что это может быть отдельной проблемой, взаимодействующей с этим.

Если вы закомментируете jQuery.change, он возвращается к нормальной желаемой одиночной обратной передаче.поведение.

Я погуглил как сумасшедший, но смог найти только один пост на форуме, с которым MIGHT столкнулся с той же проблемой.Только после того, как я определил, что проблема не возникла в Firefox, и добавил IE8 в свой список поисковых запросов, я наткнулся на сообщения об ошибках jQuery.http://dev.jquery.com/ticket/6310 http://dev.jquery.com/ticket/6593

Обходной путь (в ASP.NET) - отключить AutoPostBack и явно добавить __doPostBack в конце обработчиков событий jQuery для всех элементов управления, которые должны выполнять как клиентский, так и серверный код.

EDIT: Исправлен селектор jQuery, который, как указывал meep, пропускал #.

Ответы [ 2 ]

0 голосов
/ 02 октября 2010

Microsoft, не обращая внимания, это больше вина jQuery, чем IE.Это вызвано попыткой jQuery обойти отсутствие пузырьков для события change в IE, вызывая дополнительные поддельные change события для каждого элемента-предка, а также целевого элемента, в дополнение к событию естественного изменения.Предположительно, ошибка осталась незамеченной, поскольку запуск нескольких событий onchange обычно был бы безвредным.

(Это не ответ. Но тогда ваш вопрос не является вопросом.)

0 голосов
/ 02 октября 2010

Насколько мне известно, эта проблема ограничена Internet Explorer, поэтому, если у вас есть возможность, уберите IE у пользователей вашего приложения.

Или отключите AutoPostBack и явно добавьте __doPostBack в конце обработчиков событий jQuery для всех элементов управления, которые должны выполнять как клиентский, так и серверный код. Если вы используете элементы управления plain-old-html, не используйте inline onchange AND jQuery.change для тех же элементов.

Или взломайте jQuery самостоятельно, чтобы предотвратить повторное выполнение onchange при подключении изменений.

Или дождитесь следующего выпуска jQuery и надейтесь, что проблема устранена.

Microsoft, вероятно, никогда не поднимет палец, чтобы исправить это, так как они продолжают распространять старые ошибки IE6 вперёд в более новые версии IE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...