W3C
Создатели DOM
Прежде чем приступить к изучению технологии DOM, вы уже должны знать основы языков HTML, CSS и , помимо этого, вам необходимо прочитать статьи посвящённые HTML-формам (знать как создавать кнопки, текстовые поля и т.д.).
DOM (document object model) — объектная модель документа, создан W3C (World Wide Web Consortium) — консорциумом всемирной паутины.
DOM — это веб-технология, позволяющая управлять HTML-тегами страницы, через язык JavaScript. DOM представляет HTML-теги в виде объектов со свойствами и методами. У каждого HTML-тега (объекта) на HTML-странице, благодаря DOM, имеется свой уникальный адрес. Получая доступ к этому адресу, JavaScript может управлять HTML-тегом.
Адреса в DOM создаются автоматически, но они слишком длинные и сложные. Поэтому создатели DOM, сделали для веб-программистов возможность, самостоятельного написания коротких адресов, через селектор id (уникальный идентификатор).
Принцип работы DOMБраузер открывая HTML-страницу, создает на основе её тегов — структуру DOM, где каждый HTML-тег предстаёт в виде объекта со своим уникальным адресом. Структуру DOM также ещё называют деревом DOM , это дерево состоит из узлов, которые представляют собой HTML-теги, атрибуты, текст.
История DOMИзначально DOM не был стандартизирован и существовавшие на тот момент два браузера Netscape Navigator и Internet Explorer , создавали DOM по своему разумению. В то время, веб-программистам приходилось изучать две версии DOM.
На данный момент, W3C стандартизировал DOM и все браузеры стараются придерживаться этого стандарта.
Тема действительно сложная. Но, как говорится, не так страшен чёрт, как его малюют. Вот тут-то самый крепкий орешек достаётся мне: этакая сверхзадача «намалевать» по возможности удобоваримо, но и не совсем примитивно. Пока что все прочитанные мной материалы тяготеют либо к зауми, либо к примитиву.
Что такое DOMАббревиатура DOM расшифровывается как Document Object Model (объектная модель документа).
DOM - это программный интерфейс доступа к содержимому HTML, XHTML и XML-документов, то есть представление тэгов и атрибутов HTML, XHTML и XML, а также стилей CSS в виде объектов программирования. С этой моделью работает как JavaScript, так и другие языки web-программирования.
Немного истории
Существует 4 уровня DOM (0, 1, 2 и 3).
Уровень 0 (1996) включал в себя модели DOM , которые существовали до появления уровня 1. В основном это коллекции: document.images, document.forms, document.layers и document.all. Эти модели формально не являются спецификациями DOM , опубликованными W3C . Скорее они представляют информацию о том, что существовало до начала процесса стандартизации.
Уровень 1 (1997) включал также базовые функциональные возможности по обработке XML-документов: многочисленные способы работы с отдельными узлами, работа с инструкциями обработки XML и т.д.
Кроме того, DOM уровня 1 содержит ряд специальных интерфейсов, которые могут обрабатывать отдельные HTML-элементы. Например, можно работать с таблицами HTML, формами, списками выбора и т.д.
В DOM уровня 2 (2002) было добавлено несколько новых возможностей.
Если в DOM уровня 1 отсутствовала поддержка пространств имён, то интерфейсы DOM уровня 2 содержат методы для управления пространствами имён, связанными с требованиями к составлению и обработке XML-документов.
Помимо этого, DOM уровня 2 поддерживает события.
Уровень 2 является текущим уровнем спецификаций DOM , однако W3C рекомендует и некоторые разделы спецификаций уровня 3.
DOM уровня 3 - это рабочий проект спецификации, которая расширяет функциональность DOM уровня 2. Одна из наиболее важных особенностей этой версии спецификации заключается в возможности работать с многочисленными расширениями DOM .
Что означает «программный интерфейс»?
Английское слово interface можно перевести как «область контакта». Компьютер, грубо говоря, понимает только две вещи: пустой бит и заполненный бит. Язык, на котором «говорит» компьютер, можно представить как нескончаемую вереницу нулей и единиц, дающих бесконечное количество различных комбинаций.
Любой программный код - это вразумительная для программиста интерпретация этих «нулей и единиц», с которыми работает компьютер. Таким образом, любой язык программирования является интерфейсом человека и машины.
Браузеры работают так же, как и другие компьютерные приложения. Они интерпретируют в «нули и единицы» коды HTML, XML, CSS, скрипты JavaScript, PHP, Perl и т.д. Для работы с этим многоязычием нужна общая платформа. Этой платформой и является DOM - спецификация, не зависящая от конкретного языка программирования или разметки. Это интерфейс, который можно использовать во многих популярных языках программирования, связанных с созданием web-страниц и способных понимать и интерпретировать объекты DOM .
DOM и браузеры
DOM и JavaScript
В JavaScript вершиной иерархической лестницы объектов DOM , своеобразным «проводником» в этот интерфейс служит объект document , а объекты DOM становятся его свойствами, свойствами его свойств и т.д. Их также называют узлами DOM .
Узлы DOMВ DOM уровня 2 есть 12 типов узлов. За каждым типом узла DOM закреплена константа с уникальным именем. Большинство узлов предназначено для работы с XML . В сборке HTML - JavaScript , которой мы занимаемся, можно использовать только 5 типов. Но и эта «верхушка айсберга» представляет собой весьма «развесистое дерево», которое не охватить за одно-два занятия.
Полный набор констант типов узлов, определённый в спецификации W3C DOM (голубым подсвечены узлы, доступные для HTML - JavaScript ):
Имя константы |
Значение |
Описание |
Node.ELEMENT_NODE |
Узел элемента (возвращает корневой элемент документа, для HTML-документов это элемент HTML) |
|
Node.ATTRIBUTE_NODE |
Узел атрибута (возвращает атрибут элемента XML- или HTML-документа) |
|
Текстовый узел (#text) |
||
Node.CDATA_SECTION_NODE |
Узел секции CDATA (XML: альтернативный синтаксис для отображения символьных данных) |
|
Node.ENTITY_REFERENCE_NODE |
||
Node.ENTITY_NODE |
Узел раздела |
|
Node.PROCESSING_INSTRUCTION_NODE |
Узел директивы XML |
|
Node.COMMENT_NODE |
Узел комментария |
|
Node.DOCUMENT_NODE |
Узел документа (основа доступа к содержанию документа и создания его составляющих) |
|
Node.DOCUMENT_TYPE_NODE |
Узел типа документа (возвращает тип данного документа, т.е. значение тэга DOCTYPE) |
|
Node.DOCUMENT_FRAGMENT_NODE |
Узел фрагмента документа (извлечение части дерева документа, создание нового фрагмента документа, вставка фрагмента в качестве дочернего элемента какого-либо узла и т.п.) |
|
Node.NOTATION_NODE |
Узел нотации* |
* Нотации - это имена, идентифицирующие формат неанализируемых разделов, формат элементов, имеющих атрибут нотации, или прикладную программу, которой адресована директива. (Непонятно? Мне пока тоже не очень.)
Структура документа в модели DOM
Все объекты документа являются узлами DOM. Рассмотрим элементарный документ:
< title>DOM ЗаголовокТекст абзаца
Вот схема его DOM-дерева:
Каждый узел может иметь дочерние узлы (на схеме к ним ведут стрелки). Объект document - основание дерева документа - тоже узел, но у него нет родительского узла и имеется ряд свойств и методов, отсутствующих у других узлов. Он имеет один дочерний узел: элемент .
У элемента два дочерних узла: и , для которых дочерними становятся все элементы, содержащиеся в них.
Внимание!
«Элемент» и «тэг» не синонимы. Тэг - это знак разметки: - это два разных тэга. А элемент - объект, помеченный этими тэгами:
Текст абзаца
.Элементы , и
Содержат внутри себя текст . Это их дочерние текстовые узлы . У элемента есть также атрибут : align="center" . Узлы атрибутов - это тоже дочерние узлы элементов, которые их содержат.
При работе с узлами DOM-дерева используются их свойства и методы.
Некоторые свойства узловМаленькое вступление
Ещё раз повторю: когда мы обращаемся в скриптах к элементам страницы, то имеем дело не только с языком Javascript, но и с внедрённым в него интерфейсом DOM . Иногда необходимо отдавать себе в этом отчёт, иногда можно и забыть, «что говорим прозой».
Некоторыми свойствами и методами из объектной модели DOM мы уже таким образом пользовались. Поэтому временами я буду давать ссылки на предыдущие уроки.
В этом уроке мы не будем идти «академическим» путём, рассматривая все свойства всех узлов во всех браузерах. Для начала познакомимся с самыми практичными и «бесконфликтными» из них.
Именно поэтому не будем начинать, как принято, с «основных свойств»: nodeName и nodeValue .
tagName
Возвращает строку с именем тэга элемента. Все значения tagName содержат символы только верхнего регистра.
Синтаксис
элемент .tagNameПример
Тестируем свойство tagName
document.write (document.getElementById ("testTagName" ).tagName)
Результат
Тестируем свойство tagName
innerHTML
С этим свойством мы уже встречались (см. Урок 10). А теперь понимаем, откуда оно взялось: «из дома».
Даёт доступ к содержимому элемента. Задаёт не только текстовое содержание, но и все тэги HTML, находящиеся внутри элемента.
Это свойство не только для чтения, но и для изменения содержимого.
Примечание
В IE для ряда элементов innerHTML работает только для чтения: это все табличные элементы, за исключением
Например, мы создали пустую таблицу без элемента
IE выдаст «неизвестную ошибку выполнения», а остальные браузеры произведут вставку.
В то же время, если мы запросим существующее содержимое элемента
Синтаксис
элемент .innerHTML = "назначенный текст"Пример
Абзац для вставки // Эта функция читает текст и вставляет его в заданный абзац. function testRead() { document.getElementById ("target" ).innerHTML = document.getElementById ("testInnerHTML" ).innerHTML } // Эта функция изменяет текст заданного абзаца. function testChange() { document.getElementById ("target" ).innerHTML = "Перекрашиваем и меняем текст" } // Эта функция возвращает свойство в исходное положение. function testReset() { document.getElementById ("target" ).innerHTML = "Абзац для вставки" } |
Тестируем свойство innerHTML
Абзац для вставки
Объектная модель документа, или «DOM», является программным интерфейсом доступа к элементам веб-страниц. По сути, это API страницы, позволяющий читать и манипулировать содержимым, структурой и стилями страницы. Давайте разберемся как это устроено и как это работает.
Как строится веб-страница?Процесс преобразования исходного HTML-документа в отображаемую стилизованную и интерактивную страницу, называется “Critical Rendering Path”(“Критическим путем рендеринга”). Хотя этот процесс можно разбить на несколько этапов, как я описал это в статье «Понимание критического пути рендеринга », эти этапы можно условно сгруппировать в два этапа. В первом браузер анализирует документ, чтобы определить, что в конечном итоге будет отображаться на странице, а во второй браузер выполняет рендеринг.
Результатом первого этапа является то, что называется “render tree”(«дерево рендеринга»). Дерево рендеринга – это представление элементов HTML, которые будут отображаться на странице, и связанных с ними стилей. Чтобы построить это дерево, браузеру нужны две вещи:
DOM – это объектное представление исходного HTML-документа. Он имеет некоторые различия, как мы увидим ниже, но по сути это попытка преобразовать структуру и содержание документа HTML в объектную модель, которая может использоваться различными программами.
Структура объектов DOM представлена тем, что называется «деревом узлов». Оно так называется, потому что его можно рассматривать как дерево с одним родительским элементом, который разветвляется на несколько дочерних ветвей, каждая из которых может иметь листья. В этом случае родительский «элемент» – это корневой элемент, дочерние «ветви» – это вложенные элементы, а «листья» – это содержимое внутри элементов.
Давайте рассмотрим этот HTML-документ в качестве примера:
My first web page Hello, world!
How are you?
Этот документ может быть представлен в виде следующего дерева узлов:
- html
- head
- title
- My first web page
- title
- body
- h1
- Hello, world!
- p
- How are you?
- h1
- head
В приведенном выше примере кажется, что DOM является отображением 1: 1 исходного HTML-документа. Однако, как я уже говорил, есть различия. Чтобы полностью понять, что такое DOM, нам нужно взглянуть на то, чем он не является.
DOM не является копией исходного HTMLХотя DOM создан из HTML-документа, он не всегда точно такой же. Есть два случая, в которых DOM может отличаться от исходного HTML.
1. Когда HTML содержит ошибки разметкиDOM – это интерфейс доступа к действительных (то есть уже отображаемым) элементам документа HTML. В процессе создания DOM, браузер сам может исправить некоторые ошибки в коде HTML.
Рассмотрим в качестве примера этот HTML-документ:
Hello, world!
В документе отсутствуют элементы и , что является обязательным требованием для HTML. Но если мы посмотрим на получившееся дерево DOM, то увидим, что это было исправлено:
- html
- head
- body
- Hello, world!
Помимо того, что DOM является интерфейсом для просмотра содержимого документа HTML, он сам также может быть изменен.
Мы можем, например, создать дополнительные узлы для DOM, используя Javascript.
Var newParagraph = document.createElement("p"); var paragraphContent = document.createTextNode("I"m new!"); newParagraph.appendChild(paragraphContent); document.body.appendChild(newParagraph);
Этот код изменит DOM, но изменения не отобразятся в документе HTML .
DOM – это не то, что вы видите в браузере (то есть, дерево рендеринга)В окне просмотра браузера вы видите дерево рендеринга, которое, как я уже говорил, является комбинацией DOM и CSSOM. Чем отличается DOM от дерева рендеринга, так это то, что последнее состоит только из того, что в конечном итоге будет отображено на экране.
Поскольку дерево рендеринга имеет отношение только к тому, что отображается, оно исключает элементы, которые визуально скрыты. Например, элементы, у которых есть стили с display: none .
Hello, world!
DOM будет включать элемент
- html
- head
- body
- h1
- Hello, world!
- p
- How are you?
- h1
Однако дерево рендеринга и, следовательно, то, что видно в окне просмотра, не будет включено в этот элемент.
- html
- body
- h1
- Hello, world!
- h1
- body
Это различие немного меньше, потому что инспектор элементов DevTools обеспечивает самое близкое приближение к DOM, которое мы имеем в браузере. Однако инспектор DevTools содержит дополнительную информацию, которой нет в DOM.
Лучший пример этого – псевдоэлементы CSS. Псевдоэлементы, созданные с использованием селекторов ::before и ::after , являются частью CSSOM и дерева рендеринга, но технически не являются частью DOM. Это связано с тем, что DOM создается только из исходного HTML-документа, не включая стили, примененные к элементу.
Несмотря на то, что псевдоэлементы не являются частью DOM, они есть в нашем инспекторе элементов devtools.
РезюмеDOM – это интерфейс к HTML-документу. Он используется браузерами как первый шаг к определению того, что визуализировать в окне просмотра, и кодом Javascript для изменения содержимого, структуры или стиля страницы.
Справочник содержит описание всех свойств и методов стандартных встроенных объектов JavaScript.
Объектная модель документаОбъектная модель документа (Document Object Model, DOM) – это интерфейс программирования приложений (Application Programming Interface, API) для XML, который был расширен также для работы с HTML.
В DOM всё содержимое страницы (элементы и текст) представляется как иерархия узлов. Рассмотрим следующий код:
Простая страница
Привет Мир!
Этот код можно изобразить с помощью DOM как иерархию узлов:
Представляя документ в виде дерева узлов, DOM API предоставляет разработчикам полный контроль над содержимым и структурой веб-страницы.
При описании древовидной структуры DOM используется терминология, которая была заимствована у генеалогических деревьев.
Так, узел, расположенный непосредственно над данным узлом, называется родительским по отношению к данному узлу. Узлы, расположенные на один уровень ниже данного узла, называются дочерними по отношению к данному узлу. Узлы, находящиеся на одном уровне и имеющие одного и того же родителя, называются сестринскими или братьями . Узлы, расположенные на любое число уровней ниже данного узла, называются его потомками . Родительские, прародительские и любые другие узлы, расположенные на любое число уровней выше данного узла, называются его предками .
Справочник по DOM содержит описание объектов Document, Element, Event и NodeList, включая описание их методов и свойств:
Справочник BOMBOM (Browser Object Model в переводе с анг. - Объектная Модель Браузера) обеспечивает доступ к окну браузера и позволяет манипулировать им и его элементами.
BOM-объекты обеспечивают доступ к функционалу браузера независимо от контента веб-страницы. Тема BOM интересна и одновременно сложна, потому что из-за длительного отсутствия спецификации производители браузеров свободно расширяли BOM по своему усмотрению. Многие элементы, схожие в разных браузерах, стали стандартами де-факто, которые соблюдаются и по сей день из соображений взаимной совместимости. Чтобы стандартизировать эти фундаментальные аспекты JavaScript, консорциум W3C определил основные BOM-элементы в спецификации HTML5.
Как правило, когда нужно выполнить какие-либо действия с DOM, разработчики используют jQuery. Однако практически любую манипуляцию с DOM можно сделать и на чистом JavaScript с помощью его DOM API.
Рассмотрим этот API более подробно:
В конце вы напишете свою простенькую DOM-библиотеку, которую можно будет использовать в любом проекте.
DOM-запросыDOM-запросы осуществляются с помощью метода.querySelector() , который в качестве аргумента принимает произвольный СSS-селектор.
Const myElement = document.querySelector("#foo > div.bar")
Он вернёт первый подходящий элемент. Можно и наоборот - проверить, соответствует ли элемент селектору:
MyElement.matches("div.bar") === true
Если нужно получить все элементы, соответствующие селектору, используйте следующую конструкцию:
Const myElements = document.querySelectorAll(".bar")
Если же вы знаете, на какой родительский элемент нужно сослаться, можете просто проводить поиск среди его дочерних элементов, вместо того чтобы искать по всему коду:
Const myChildElemet = myElement.querySelector("input") // Вместо: // document.querySelector("#foo > div.bar input")
Возникает вопрос: зачем тогда использовать другие, менее удобные методы вроде.getElementsByTagName() ? Есть маленькая проблема - результат вывода.querySelector() не обновляется, и когда мы добавим новый элемент (смотрите ), он не изменится.
Const elements1 = document.querySelectorAll("div") const elements2 = document.getElementsByTagName("div") const newElement = document.createElement("div") document.body.appendChild(newElement) elements1.length === elements2.length // false
Также querySelectorAll() собирает всё в один список, что делает его не очень эффективным.
Как работать со списками?Вдобавок ко всему у.querySelectorAll() есть два маленьких нюанса. Вы не можете просто вызывать методы на результаты и ожидать, что они применятся к каждому из них (как вы могли привыкнуть делать это с jQuery). В любом случае нужно будет перебирать все элементы в цикле. Второе - возвращаемый объект является списком элементов, а не массивом. Следовательно, методы массивов не сработают. Конечно, есть методы и для списков, что-то вроде.forEach() , но, увы, они подходят не для всех случаев. Так что лучше преобразовать список в массив:
// Использование Array.from() Array.from(myElements).forEach(doSomethingWithEachElement) // Или прототип массива (до ES6) Array.prototype.forEach.call(myElements, doSomethingWithEachElement) // Проще: .forEach.call(myElements, doSomethingWithEachElement)
У каждого элемента есть некоторые свойства, ссылающиеся на «семью».
MyElement.children myElement.firstElementChild myElement.lastElementChild myElement.previousElementSibling myElement.nextElementSibling
Поскольку интерфейс элемента (Element) унаследован от интерфейса узла (Node), следующие свойства тоже присутствуют:
MyElement.childNodes myElement.firstChild myElement.lastChild myElement.previousSibling myElement.nextSibling myElement.parentNode myElement.parentElement
Первые свойства ссылаются на элемент, а последние (за исключением.parentElement) могут быть списками элементов любого типа. Соответственно, можно проверить и тип элемента:
MyElement.firstChild.nodeType === 3 // этот элемент будет текстовым узлом
Добавление классов и атрибутовДобавить новый класс очень просто:
MyElement.classList.add("foo") myElement.classList.remove("bar") myElement.classList.toggle("baz")
Добавление свойства для элемента происходит точно так же, как и для любого объекта:
// Получение значения атрибута const value = myElement.value // Установка атрибута в качестве свойства элемента myElement.value = "foo" // Для установки нескольких свойств используйте.Object.assign() Object.assign(myElement, { value: "foo", id: "bar" }) // Удаление атрибута myElement.value = null
Можно использовать методы.getAttibute() , .setAttribute() и.removeAttribute() . Они сразу же поменяют HTML-атрибуты элемента (в отличие от DOM-свойств), что вызовет браузерную перерисовку (вы сможете увидеть все изменения, изучив элемент с помощью инструментов разработчика в браузере). Такие перерисовки не только требуют больше ресурсов, чем установка DOM-свойств, но и могут привести к непредвиденным ошибкам.
Как правило, их используют для элементов, у которых нет соответствующих DOM-свойств, например colspan . Или же если их использование действительно необходимо, например для HTML-свойств при наследовании (смотрите ).
Добавление CSS-стилейДобавляют их точно так же, как и другие свойства:
MyElement.style.marginLeft = "2em"
Какие-то определённые свойства можно задавать используя.style , но если вы хотите получить значения после некоторых вычислений, то лучше использовать window.getComputedStyle() . Этот метод получает элемент и возвращает CSSStyleDeclaration , содержащий стили как самого элемента, так и его родителя:
Window.getComputedStyle(myElement).getPropertyValue("margin-left")
Изменение DOMМожно перемещать элементы:
// Добавление element1 как последнего дочернего элемента element2 element1.appendChild(element2) // Вставка element2 как дочернего элемента element1 перед element3 element1.insertBefore(element2, element3)
Если не хочется перемещать, но нужно вставить копию, используем:
// Создание клона const myElementClone = myElement.cloneNode() myParentElement.appendChild(myElementClone)
Метод.cloneNode() принимает булевое значение в качестве аргумента, при true также клонируются и дочерние элементы.
Конечно, вы можете создавать новые элементы:
Const myNewElement = document.createElement("div") const myNewTextNode = document.createTextNode("some text")
А затем вставлять их как было показано выше. Удалить элемент напрямую не получится, но можно сделать это через родительский элемент:
MyParentElement.removeChild(myElement)
Можно обратиться и косвенно:
MyElement.parentNode.removeChild(myElement)
Методы для элементовУ каждого элемента присутствуют такие свойства, как.innerHTML и.textContent , они содержат HTML-код и, соответственно, сам текст. В следующем примере изменяется содержимое элемента:
// Изменяем HTML myElement.innerHTML = ` New content { el.addEventListener("change", function (event) { console.log(event.target.value) }) })
Предотвращение действий по умолчаниюДля этого используется метод.preventDefault() , который блокирует стандартные действия. Например, он заблокирует отправку формы, если авторизация на клиентской стороне не была успешной:
MyForm.addEventListener("submit", function (event) { const name = this.querySelector("#name") if (name.value === "Donald Duck") { alert("You gotta be kidding!") event.preventDefault() } })
Метод.stopPropagation() поможет, если у вас есть определённый обработчик события, закреплённый за дочерним элементом, и второй обработчик того же события, закреплённый за родителем.
Как говорилось ранее, метод.addEventListener() принимает третий необязательный аргумент в виде объекта с конфигурацией. Этот объект должен содержать любые из следующих булевых свойств (по умолчанию все в значении false):
- capture: событие будет прикреплено к этому элементу перед любым другим элементом ниже в DOM;
- once: событие может быть закреплено лишь единожды;
- passive: event.preventDefault() будет игнорироваться (исключение во время ошибки).
Наиболее распространённым свойством является.capture , и оно настолько распространено, что для этого существует краткий способ записи: вместо того чтобы передавать его в объекте конфигурации, просто укажите его значение здесь:
MyElement.addEventListener(type, listener, true)
Обработчики удаляются с помощью метода.removeEventListener() , принимающего два аргумента: тип события и ссылку на обработчик для удаления. Например свойство once можно реализовать так:
MyElement.addEventListener("change", function listener (event) { console.log(event.type + " got triggered on " + this) this.removeEventListener("change", listener) })
НаследованиеДопустим, у вас есть элемент и вы хотите добавить обработчик событий для всех его дочерних элементов. Тогда бы вам пришлось прогнать их в цикле, используя метод myForm.querySelectorAll("input") , как было показано выше. Однако вы можете просто добавить элементы в форму и проверить их содержимое с помощью event.target .
MyForm.addEventListener("change", function (event) { const target = event.target if (target.matches("input")) { console.log(target.value) } })
И ещё один плюс данного метода заключается в том, что к новым дочерним элементам обработчик будет привязываться автоматически.
АнимацияПроще всего добавить анимацию используя CSS со свойством transition . Но для большей гибкости (например для игры) лучше подходит JavaScript.
Вызывать метод window.setTimeout() , пока анимация не закончится, - не лучшая идея, так как ваше приложение может зависнуть, особенно на мобильных устройствах. Лучше использовать window.requestAnimationFrame() для сохранения всех изменений до следующей перерисовки. Он принимает функцию в качестве аргумента, которая в свою очередь получает метку времени:
Const start = window.performance.now() const duration = 2000 window.requestAnimationFrame(function fadeIn (now)) { const progress = now - start myElement.style.opacity = progress / duration if (progress < duration) { window.requestAnimationFrame(fadeIn) } }
Таким способом достигается очень плавная анимация. В своей статье Марк Браун рассуждает на данную тему.
Пишем свою библиотекуТот факт, что в DOM для выполнения каких-либо операций с элементами всё время приходится перебирать их, может показаться весьма утомительным по сравнению с синтаксисом jQuery $(".foo").css({color: "red"}) . Но почему бы не написать несколько своих методов, облегчающую данную задачу?
Const $ = function $ (selector, context = document) { const elements = Array.from(context.querySelectorAll(selector)) return { elements, html (newHtml) { this.elements.forEach(element => { element.innerHTML = newHtml }) return this }, css (newCss) { this.elements.forEach(element => { Object.assign(element.style, newCss) }) return this }, on (event, handler, options) { this.elements.forEach(element => { element.addEventListener(event, handler, options) }) return this } } }
Введите ключевые слова.