Номер телефона

Последнее обновление:

О событиях изменения тегов javascript

Язык javascript содержит возможности использования и управления многочисленными событиями. В основном, они касаются действий пользователя, таких, как клик или иное действие мыши, нажатие клавиши, прокрутка вебстраницы и т.д. Но, есть еще другой тип событий, которые сигнализируют, в частности, об изменении структуры html-кода вебстраницы или, точнее, об изменении ее DOM.

Одними из таких событий является события изменения html-тегов. Примеры изменения тегов:

  • Изменилось содержимое (innerHTML или textContent),
  • Изменился состав, названия, значения атрибутов (одного или нескольких),
  • Изменился сам тег (к примеру, тег <p> превратился в <div>).

Так вот, такие изменения можно тоже отслеживать. Иногда это нужно.

Как правило, разработчики сайтов нечасто используют такую функциональность.

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

Особое значение таких событий – когда они применяются для отслеживания редактируемых тегов, т.е. у которых имеется атрибут contenteditable=”true”. Это может быть актуально для текстовых (и иных) редакторов, а также, впрочем, и для ряда технических целей. Мы здесь не будем их касаться.

Используются две модели событий изменения тегов

Это - Mutation events и MutationObserver. Перечислять события каждого из этих видов не будем; видимо, читателю будет проще самостоятельно перейти по ссылкам и прочитать об этом, при желании.

События первого вида (Mutation events) являются на дату написания статьи (август 2022 г.) уже устаревшими, deprecated. Использование их не рекомендуется. Вместе с тем, в ряде особенно старых браузеров (выпущенных лет 7…10 и более назад) присутствуют именно они, а MutationObserver – еще нет.

Использование устаревших Mutation events не рекомендуется потому, что они, мол, излишне нагружают браузер – именно так это объясняют разработчики браузеров… Однако, почему, как, зачем? – на это адекватных ответов нет. Почему-то.

Вот что удалось обнаружить применительно к Mutation events

Для проверки - обработчик одного из таких событий (в частности, DOMNodeInserted) был назначен на ОДИН тег <div>, имеющий атрибут contenteditable=”true”. Т.е. это тег, в котором можно набирать/редактировать текст, а также вставлять текст, рисунки, таблицы…

Понятно, что если, скажем, назначить его на весь document (чего уж мелочиться, мол) – тогда, да, тормоза у браузера, разумеется, будут – при мало-мальски серьезном интерактивном взаимодействии со страницей.

Если взять браузеры Firefox, то в 24-й версии они (эти устаревшие события) работают без каких-либо проблем. Никакой особой «нагрузки» на браузер не ощущается. А вот уже в Firefox 36 вдруг возникла проблема: обработчик события DOMNodeInserted вел себя, как минимум, странно, срабатывая множество раз без причины.

Например, при вставке в этот тег небольшой таблицы (размером 2*2, в каждой ячейке которой находились однозначные цифры, типа 1, 2, 3, 4), скопированной из Word в буфер обмена, обработчик срабатывал 10 и даже более раз.

Примечание. При копировании из Word объем контента, находящегося в буфере обмена, составлял примерно 3 кБ. Если кто думает, что при копировании столь простой таблицы размером 2*2, копируется лишь несколько байтов контента, он сильно заблуждается. Дело в том, что Word снабжает таблицу достаточно большим количеством разных стилей, классов. Также копируются теги (<tr>, <td> и т.д.; а у этих тегов – еще куча разных атрибутов).

Чтобы выяснить причину, при каждом срабатывании обработчика делался вызов alert(), который показывал размер (число символов) html-кода, загруженного в редактируемый тег.

И оказалось очень любопытно. Браузер Firefox 24 вставляет таблицу из буфера обмена сразу, за один прием. При этом объем вставленного html-кода таблицы СРАЗУ равнялся его фактическому объему и, что важно, НЕ менялся в процессе работы обработчика. А вот Firefox 36 вел себя совсем по-другому: он почему-то вставлял html-код таблицы из буфера обмена не сразу, а… порциями. При том, что вставка-то была сделана, разумеется, ОДИН раз.

Так вот, в случае с Firefox 36 вставка каждой(!) порции html-кода таблицы вызывала срабатывание обработчика события DOMNodeInserted! Тогда как в Firefox 24, повторимся, такого не было, там обработчик срабатывал 1 раз.

Конечно, о причинах такого странного поведение FF36 судить трудно, не вникнув в исходные коды этого браузера. На наш взгляд, это может быть вызвано тем фактом, что вставка содержимого буфера обмена в этом браузере происходит не сразу («оптом»), а небольшими порциями. Видимо, так сделано для оптимизации скорости работы браузера. Ну, а каждая порция, естественно, вызывает срабатывание обработчика изменения редактируемого тега (в который происходит вставка) вновь и вновь. Потому как тег-то (точнее, его innerHTML) изменяется при вставке каждой порции!

Это означает, что, по-видимому, разработчики Firefox на каком-то этапе решили изменить технологию работы браузера, в том числе, технологию вставки из буфера обмена.

Т.е. понятно, что для конечного пользователя эти нюансы незаметны и вникать в них он, скорее всего, не будет. Как там происходит вставка из буфера обмена – частично или сразу. Главное, чтобы без лишних вопросов и побыстрее, да и всё. А вот для разработчика, если он будет использовать события Mutation events, это является, конечно же, весьма актуальным. И даже критичным во всех тех случаях, когда объем вставки из буфера обмена будет достаточно большим. Тогда обработчик таких событий в более новых браузерах будет вызван СТОЛЬКО раз, что… Что мало-мальски серьезная работа с браузером будет и в самом деле поставлена под вопрос.

И, видимо, именно ЭТО-то и понудило разработчиков браузеров отказаться от устаревшей модели событий в пользу новой.

Да, видимо, именно ЭТОТ  нюанс и побудил разработчиков браузеров перейти на новую модель событий изменения тегов

Т.е. от Mutation events перешли к MutationObserver. Следует отметить, что для последних событий обработчик срабатывает одинаково как в FF24, так и в FF36. Т.е. не было тех многократных срабатываний, вызванных тем фактом, что в более новом браузере вставка из буфера обмена в редактируемый тег происходит не сразу, а порциями.

Поэтому если кто-то из разработчиков решится использовать устаревшие события Mutation events, этот момент следует принять во внимание.

Кстати, а как в Enternet Explorer?

В частности, в IE11. Следует отметить, что устаревшие события (Mutation events) не работали в нем от слова совсем.

Правда, для проверки был использован «файрфоксовский» способ обработки этих событий; вполне возможно, что в Enternet Explorer 11 применяется какой-то свой механизм их обработки (как, впрочем, и многое другое конкретно в браузерах этой линейки). Следовательно, в более старых версиях IE они работать, скорее всего, тоже не будут.

Кстати, если судить по информации от сервиса caniuse.com, для браузеров линейки IE указана «частичная» поддержка событий Mutation events. Однако, по крайней мере, на событие DOMNodeInserted это не распространяется.

Тогда как новые события (MutationObserver) работали в Enternet Explorer без особых замечаний – так, как полагается. Правда, наблюдаются небольшие нюансы по сравнению с браузерами Firefox, но это уже, скорее, мелочи.

Поэтому, на наш взгляд, в настоящее время можно уже смело забыть о Mutation events. Пользы от них – немного, разве что, для совсем уж старых браузеров. А вот вред для более новых браузеров – есть и немало. Тем более, что в определенном будущем эти события в новых браузерах поддерживаться, скорее всего, уже не будут.

А что делать, если все-таки в браузере не поддерживается модель MutationObserver?

Например, в браузерах типа Opera mini.

Впрочем, там и Mutation events тоже не поддерживается.

Ну, тогда – лучше вообще отказаться от таких событий и сделать высокоуровневую их реализацию (т.е. уже средствами самого javascript). Например, путем установки таймера, срабатывающего через разумный срок, скажем, через полсекунды. И, по таймеру, анализировать изменение тех тегов, за которыми необходимо следить. Это – самый простой, универсальный способ. Но, увы, и довольно затратный по ресурсам. Тем более, что, по крайней мере, проверка тегов по таймеру все же не приведет к многочисленным срабатываниям обработчика событий – как это наблюдалось в Firefox 36 при вставке из буфера обмена даже сравнительно небольшого контента (порядка 3 кБ). К тому же, проверку по таймеру можно подключить лишь тогда, когда надо и отключить, если нет в ней необходимости.


Комментарии:
Всего комментариев:0
Пожалуйста, не забудьте ознакомиться с правилами оставления комментариев.



Подписаться на комментарии на этой странице

Мы можем выполнить

Другие услуги
Интересная и полезная
информация
НАПИШИТЕ НАМ
Яндекс.Метрика
Номер телефона
© Copyright Все права защищены 2013-2024 Научный консалтинг