5 причин избегать 'innerHTML’ при использовании JavaScript для изменения DOM

Вступление

Когда я писал базовый JS для манипуляций с DOM и прослушивания событий, я обнаружил ошибку, которая поставила меня в тупик. Я потратил время на изучение Stack Overflow в поисках решения, но безрезультатно. Чтобы воспроизвести ошибку, я представлю упрощенную версию своего кода.

Для начала у меня был простой HTML-файл с одним div в теле:

В файле JavaScript я добавил несколько узлов в DOM и создал прослушиватель событий на кнопке:

В браузере моя страница появилась как положено. Есть изображение, за которым следует кнопка и дополнительный текст, который я добавил в DOM.

С первого взгляда на код у кнопки есть четко определенное назначение. При щелчке по нему на консоль должна выводиться строка hello. Однако при нажатии кнопки ничего не печатается. Почему?

Во-первых, давайте попробуем выяснить, где в код вносится ошибка. Для начала закомментирую строку div.innerHTML +=.

Теперь, когда я нажимаю кнопку, все работает как положено. После нажатия кнопки hello регистрируется в консоли.

Очевидно, что строка с innerHTML += вызывает серьезные проблемы. Программисту JS кажется естественным использование таких операторов, как ++ и +=. Однако использование оператора += с innerHTML вызовет серьезные проблемы. Ниже мы обсудим, почему.

Добавление к 'innerHTML' повторяет анализ всего тега

Когда вы используете оператор добавления с innerHTML, Javascript повторно анализирует содержимое всего тега и воссоздает все элементы HTML.

'innerHTML' очень медленно

Как естественный побочный эффект предыдущей причины, повторный анализ делает innerHTML чрезвычайно медленным. Для небольшого HTML-документа со статическим текстом это может не быть проблемой. Однако для больших документов процесс повторного анализа занимает очень много времени и может иметь непредвиденные побочные эффекты.

'innerHTML’ Удаляет прослушиватели событий

Самый очевидный вывод из нашего краткого эксперимента: innerHTML удаляет прослушиватели событий, которые ранее были добавлены в DOM. Поскольку весь тег (div в нашем коде) повторно анализируется, прослушиватель событий теряется в процессе. Вместо использования оператора += используйте функции DOM, такие как append().

'innerHTML’ представляет угрозу безопасности

Использование innerHTML создает потенциальную угрозу безопасности вашего веб-сайта. Злоумышленники могут использовать межсайтовые сценарии (XSS) для добавления вредоносных клиентских сценариев, которые крадут личную информацию пользователя, хранящуюся в файлах cookie сеанса.

Вы можете прочитать Документацию MDN на innerHTML.

Совместимые с W3C методы позволяют легко добавлять новые элементы DOM

Такие методы, как .createElement(), appendChild(), append() и removeChild(), позволяют безопасно манипулировать DOM без непредвиденных последствий innerHTMLinnerHTML+=, в частности). Если вы просто не устанавливаете текст внутри тега HTML, например <p> или <div>, держитесь подальше от innerHTML.

Для начинающих innerHTML кажется самым простым и элегантным способом манипулировать базовыми элементами в DOM. Однако по мере того, как ваш JS становится более задействованным, а ваш DOM увеличивается в размере, innerHTML ухудшает производительность и создает риски для безопасности.

Ссылки и дополнительная литература