3

В следующем коде (JSFiddle here):Удаления предка во время фазы событий кипящего

<form> 
    <button>ok</button> 
</form> 
$(function(){ 
    $('form').submit(false) ; 
    $('button').click(function(){ $('form').remove() }) ; 
}) ; 

При щелчок по кнопке в Google Chrome 48, это вызывает форму представление.
Если вы делаете это в Firefox 43, однако отправка формы отсутствует.

Мне кажется, что поведение Firefox должно быть правильным, но поскольку у меня нет такого глубокого знания стандарта, я действительно не знаю.

Является ли поведение неправильным или ошибочным?


Развейте:
Я только что узнал, что же тест, но без использования JQuery не влечет за собой представление формы ни в одном браузере.

<form onsubmit="return false"> 
    <button onclick="form.remove()">ok</button> 
</form> 

Это не может быть проблемой синхронизации, поскольку в Javascript нет параллелизма потоков. События потоков всегда будут выполняться последовательно, поэтому обработчик события button должен завершиться до запуска обработчика событий form.
Я слепой здесь. jQuery должен делать некоторые странные громоздкие вещи, чтобы это произошло в Chrome.


Последующие 2:
Это не проблема JQuery. В JQuery багтрекер мне сказали, что встроенные обработчики событий не следуют той же спецификации, привязанных с addEventListener, поэтому истинный функционально эквивалентный код должен быть таким:

<form> 
    <button>ok</button> 
</form> 
<script> 
document.querySelector('form').addEventListener('submit',function(){ return false }) ; 
document.querySelector('button').addEventListener('click',function(evt){ evt.target.form.remove() }) ; 
</script> 

И это действительно ведет себя как JQuery версия.

+0

@Oriol, говорится в документе: «Этот метод является ярлыком для' .on («submit», handler) '" – GetFree

+0

О, я вижу. Я не могу найти его в документах, но 'on' does' if (fn === false) fn = returnFalse'. Я добавил ответ. – Oriol

+0

@Oriol, документация для этого описана в параметре 'handler'. – GetFree

ответ

0

Ваш первый код добавляет слушателю returnFalse JQuery событий:

$('form').submit(false); 

В качестве слушателя событий JQuery, return false эквивалентно

event.stopPropagation(); 
event.preventDefault(); 

Чем позже должно препятствовать представлению формы.

Однако перед началом работы submit вы используете $.fn.remove. Это не только удаляет форму из документа, но и очищает данные jQuery, включая прослушиватель событий.

Таким образом, когда браузер запускает событие submit к форме, он не отменяется.

Тогда браузеры ведут себя по-разному (demo):

  • Firefox не представляет удаленные формы
  • Chrome не заботится, была ли удалена форма и подает его в любом случае

If вы не хотите удалять данные jQuery, вы должны удалить форму, используя методы vanilla-js вместо $.fn.remove.


Во втором коде вы отменяете событие в обработчике событий vanilla-js.

Поскольку данные не являются jQuery, $.fn.remove не удаляет его, поэтому событие submit аннулируется и форма не отправляется.


В вашем третьем коде, вы удалите формы с помощью ваниль-JS методы, поэтому его данные Jquery не убираются.

Это не имеет значения, потому что приемник событий submit добавлен с помощью ванили-js.

Однако событие не аннулируется. Это связано с тем, что, в отличие от обработчиков событий vanilla-js и прослушивателей событий jQuery, значение, возвращаемое в прослушиватель событий vanilla-js, полностью игнорируется.

Так что в конце результат такой же, как в первом коде, но они не эквивалентны.

Если вы хотите отменить событие, используя ваниль-JS слушателя событий, вы должны использовать

event.preventDefault(); 

Это сделало бы его вести себя как второй код.

+0

Отличный ответ. Теперь возникает вопрос, почему Chrome отправляет удаленную форму. Такое поведение, безусловно, новое в Chrome 48. Один из моих проектов начал работать неправильно из-за этого сразу после обновления до версии 48. – GetFree

+0

@GetFree Вы уверены? Я пытался делить пополам, но даже Chromium 16 отправляет форму. – Oriol

+0

Я забыл упомянуть одну маленькую деталь. В моем проекте я использую '

' элементы, а не '
' элементов. 'Submit (false)' - это так, что диалог не отправляется, когда в диалоговом окне есть кнопка. В январе этот механизм прекратил работу. Поэтому я построил минимальный тестовый пример, чтобы воспроизвести проблему и увидел, что нет никакой разницы между использованием 'form' и' dialog', поэтому я просто предположил, что все, что заставило мой проект прекратить работу, повлияло на оба. – GetFree

0

Я думаю, что это зависит от реализации и не гарантирует идентичное поведение

+0

Есть ли источник, на который вы можете ссылаться? – GetFree

+1

я думаю это. Я не могу найти приоритет в отношении формы и это событие отправки элемента: https://www.w3.org/TR/html5/forms.html#implicit-submission –

+1

и процесс уничтожения формы может быть выполнен немедленно или может быть отложен и выполняется после формы и обработчиков ее элементов. –

0

Оба Chromium и Firefox не вызывает form.onsubmit обработчик установлен $ («форма»). Представить (...), когда $ (» form '). remove(). Таким образом, это означает, что форма проверяется как уничтоженная (или реально уничтоженная), прежде чем вызывать onsubmit как в Chromium, так и в Firefox.

Я думаю, что Chromium не проверяет, что форма, помеченная как уничтоженная, когда действие по умолчанию отправляет действие, испускаемое нажатием кнопки. Но Chromium проверяет флажок preventDefault, где по умолчанию действует кнопка submit. Таким образом, можно добавлять event.preventDefault() до или после $ ('form'). Remove().

В противоположном Firefox игнорировать preventDefault кнопки нажатия события и управления передачей для form.onsubmit.

Так что поведение этих двух браузеров в отношении preventDefault и onsubmit в точности противоположно.

Что касается факта отправки формы, когда форма отмечена как уничтоженная, можно представить себе дизайн программного обеспечения, где объект фактически удален после завершения связи, а не раньше. Но мне кажется, что это ошибка. Нужно знать, что думают разработчики. Знает ли он об этом и является ли эта ошибка или функция.