Что такое dom в javascript. Еще один блог веб разработчика. Добавление и удаление узлов

Основным инструментом работы и динамических изменений на странице является DOM (Document Object Model) - объектная модель, используемая для XML/HTML-документов.

Согласно DOM-модели, документ является иерархией.
Каждый HTML-тег образует отдельный элемент-узел, каждый фрагмент текста - текстовый элемент, и т.п.

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

Простейший DOM

Построим, для начала, дерево DOM для следующего документа.

Заголовок Прекрасный документ

Самый внешний тег - , поэтому дерево начинает расти от него.

Внутри находятся два узла: и - они становятся дочерними узлами для .

Теги образуют узлы-элементы (element node). Текст представлен текстовыми узлами (text node). И то и другое - равноправные узлы дерева DOM.

Пример посложнее

Рассмотрим теперь более жизненную страничку:

О лосях Правда о лосях.

  • Лось - животное хитрое
  • .. И коварное
  • Корневым элементом иерархии является html . У него есть два потомка. Первый - head , второй - body . И так далее, каждый вложенный тег является потомком тега выше:

    На этом рисунке синим цветом обозначены элементы-узлы, черным - текстовые элементы.

    Дерево образовано за счет синих элементов-узлов - тегов HTML.

    А вот так выглядит дерево, если изобразить его прямо на HTML-страничке:

    Кстати, дерево на этом рисунке не учитывает текст, состоящий из одних пробельных символов. Например, такой текстовый узел должен идти сразу после . DOM, не содержащий таких "пустых" узлов, называют "нормализованным" .

    Рассмотрим чуть более сложный документ.

    Документ Data

    • Осторожно
    • Информация
    Made in Russia

    Верхний тег - html , у него дети head и body , и так далее. Получается дерево тегов:

    Атрибуты

    В этом примере у узлов есть атрибуты: style , class , id . Вообще говоря, атрибуты тоже считаются узлами в DOM-модели, родителем которых является элемент DOM, у которого они указаны.

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

    Вообще-то это секрет, но DOCTYPE тоже является DOM-узлом, и находится в дереве DOM слева от HTML (на рисунке этот факт скрыт).

    P.S. Насчет секрета - конечно, шутка, но об этом и правда далеко не все знают. Сложно придумать, где такое знание может пригодиться...

    Нормализация в различных браузерах

    При разборе HTML Internet Explorer сразу создает нормализованный DOM, в котором не создаются узлы из пустого текста.

    Firefox - другого мнения, он создает DOM-элемент из каждого текстового фрагмента.
    Поэтому в Firefox дерево этого документа выглядит так:

    На рисунке для краткости текстовые узлы обозначены просто решеткой. У body вместо 3 появилось 7 детей.

    Opera тоже имеет чем похвастаться. Она может добавить лишний пустой элемент "просто от себя".

    Чтобы это увидеть - откройте документ . Он выдает число дочерних узлов document.body , включая текстовые узлы.

    У меня получается 3 для IE, 7 для Firefox и 8 (!?) для Opera.

    На практике эта несовместимость не создает больших проблем, но нужно о ней помнить. Например, разница может проявить себя в случае перебора узлов дерева.

    Возможности, которые дает DOM

    Зачем, кроме красивых рисунков, нужна иерархическая модель DOM?

    Очень просто:

    Каждый DOM-элемент является объектом и предоставляет свойства для манипуляции своим содержимым, для доступа к родителям и потомкам.

    Для манипуляций с DOM используется объект document .
    Используя document , можно получать нужный элемент дерева и менять его содержание.

    Например, этот код получает первый элемент с тэгом ol , последовательно удаляет два элемента списка и затем добавляет их в обратном порядке:

    Var ol = document.getElementsByTagName("ol") var hiter = ol.removeChild(ol.firstChild) var kovaren = ol.removeChild(ol.firstChild) ol.appendChild(kovaren) ol.appendChild(hiter)

    Для примера работы такого скрипта - кликните на тексте на лосиной cтраничке

    В старых руководствах и скриптах можно встретить модификацию HTML-кода страницы напрямую вызовом document.write .

    В современных скриптах этот метод почти не используется, случаи его правильного применения можно пересчитать по пальцам.

    Избегайте document.write.. Кроме случаев, когда вы действительно знаете, что делаете (а зачем тогда читаете самоучитель - вы и так гуру)

    Разберем подробнее способы доступа и свойства элементов DOM.

    Доступ к элементам

    Любой доступ и изменения DOM берут свое начало от объекта document .

    Начнем с вершины дерева.

    document.documentElement

    Самый верхний тег. В случае корректной HTML-страницы, это будет .

    document.body

    Тег , если есть в документе (обязан быть).

    Следующий пример при нажатии на кнопку выдаст текстовое представление объектов document.documentElement и document.body . Сама строка зависит от браузера, хотя объекты везде одни и те же.

    function go() { alert(document.documentElement) alert(document.body) }

    Типы DOM-элементов

    У каждого элемента в DOM-модели есть тип. Его номер хранится в атрибуте elem.nodeType

    Всего в DOM различают 12 типов элементов.

    Обычно используется только один: Node.ELEMENT_NODE , номер которого равен 1. Элементам этого типа соответствуют HTML-теги.

    Иногда полезен еще тип Node.TEXT_NODE , который равен 3. Это текстовые элементы.

    Остальные типы в javascript программировании не используются.

    Следующий пример при нажатии на кнопку выведет типы document.documentElement , а затем тип последнего потомка узла document.body . Им является текстовый узел.

    function go() { alert(document.documentElement.nodeType) alert(document.body.lastChild.nodeType) } Текст

    Пример

    Например, вот так выглядел бы в браузере документ из примера выше, если каждый видимый элемент обвести рамкой с цифрой nodeType в правом верхнем углу.

    ... Data

    • Осторожно
    • Информация
    Made in Russia

    Здесь показаны только элементы внутри body , т.к только они отображаются на странице. Для элементов типа 1 (теги) в скобочках указан соответствующий тег, для текстовых элементов (тип 3) - стоит просто цифра.

    Дочерние элементы
  • Все дочерние элементы, включая текстовые находятся в массиве childNodes .

    В следующем примере цикл перебирает всех детей document.body .

    For(var i=0; i BODY

    style

    Это свойство управляет стилем. Оно аналогично установке стиля в CSS.

    Например, можно установить element.style.width:

    Исходный код этой кнопки:

    Есть общее правило замены - если CSS-атрибут имеет дефисы, то для установки style нужно заменить их на верхний регистр букв.

    Например, для установки свойства z-index в 1000, нужно поставить:

    Element.style.zIndex = 1000

    innerHTML

    Когда-то это свойство поддерживалось только в IE. Теперь его поддерживают все современные браузеры.

    Оно содержит весь HTML-код внутри узла, и его можно менять.

    Свойство innerHTML применяется, в основном, для динамического изменения содержания страницы, например:

    Document.getElementById("footer").innerHTML = "Bye! "

    Пожалуй, innerHTML - одно из наиболее часто используемых свойств DOM-элемента.

    className

    Это свойство задает класс элемента. Оно полностью аналогично html-атрибуту "class".

    Elem.className = "newclass"

    onclick , onkeypress, onfocus ...

    И другие свойства, начинающиеся на "on...", хранят функции-обработчики соответствующих событий. Например, можно присвоить обработчик события onclick .

    Подробнее об этих свойствах и обработчиках событий - см.

    При открытии любого HTML документа браузер предварительно производит разбор его содержимого и на основе этого разбора создает объектную модель HTML документа или более коротко DOM .

    DOM состоит из вложенных друг в друга иерархически расположенных объектов, которые называются узлами . Каждый узел в структуре представляет располагающийся на странице HTML элемент.

    Используя DOM Вы можете взаимодействовать (считывать, изменять, удалять ) с содержимым HTML документов из скриптов.

    Ниже располагается код HTML документа и DOM, которая бы была создана браузером на основе этого кода:

    HTML DOM HTML DOM.

    Привет всем.

    Все прямоугольники изображенные на картинке являются объектами (или узлами). Разным цветом на изображение отмечены узлы разного типа .

    Красным цветом отмечен узел Document. Любое обращение к DOM должно начинаться с обращения к данному узлу.

    Зеленым цветом отмечены элементные узлы . Для каждого HTML элемента на странице браузер создает соответствующий элементный узел.

    Содержимое элементов хранится в текстовых узлах . Текстовые узлы отмечены на нашей схеме синим цветом.

    Для каждого атрибута HTML элемента создается атрибутный узел . Атрибутный узел отмечен на схеме розовым цветом.

    Обратите внимание: не забывайте, что текст всегда хранится в текстовых узлах, а не является свойством элемента. Т.е. для того, чтобы обратиться к содержимому HTML элемента Вы должны обратиться к свойству его текстового узла.

    Отношения между узлами

    Узлы в объектной структуре связаны друг с другом. Существует несколько специальных терминов для описания отношений между узлами:

    Родительский узел (parent node ) - родительским узлом по отношению к рассматриваемому объекту является узел, в который вложен рассматриваемый объект. На нашей схеме по отношению к узлам и

    является родительским. Для узла родительским является узел .

    Узлы-потомки (child node ) - узлом-потомком по отношению к рассматриваемому объекту является узел, который вложен в рассматриваемый объект. На нашей схеме по отношению к узлу и

    Являются потомками. Для узла потомком является .

    Узлы-братья (sibling node ) - узлы находящиеся на одинаковом уровне вложенности по отношению к их родительскому узлу. На нашей схеме узлами-братьями являются и ,

    Самый верхний узел в DOM называется корневым . На нашей схеме корневым является (т.к. объект document не является частью DOM).

    Справочник содержит описание всех свойств и методов стандартных встроенных объектов JavaScript.

    Объектная модель документа

    Объектная модель документа (Document Object Model, DOM) – это интерфейс программирования приложений (Application Programming Interface, API) для XML, который был расширен также для работы с HTML.

    В DOM всё содержимое страницы (элементы и текст) представляется как иерархия узлов. Рассмотрим следующий код:

    Простая страница

    Привет Мир!

    Этот код можно изобразить с помощью DOM как иерархию узлов:

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

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

    Так, узел, расположенный непосредственно над данным узлом, называется родительским по отношению к данному узлу. Узлы, расположенные на один уровень ниже данного узла, называются дочерними по отношению к данному узлу. Узлы, находящиеся на одном уровне и имеющие одного и того же родителя, называются сестринскими или братьями . Узлы, расположенные на любое число уровней ниже данного узла, называются его потомками . Родительские, прародительские и любые другие узлы, расположенные на любое число уровней выше данного узла, называются его предками .

    Справочник по DOM содержит описание объектов Document, Element, Event и NodeList, включая описание их методов и свойств:

    Справочник BOM

    BOM (Browser Object Model в переводе с анг. - Объектная Модель Браузера) обеспечивает доступ к окну браузера и позволяет манипулировать им и его элементами.

    BOM-объекты обеспечивают доступ к функционалу браузера независимо от контента веб-страницы. Тема BOM интересна и одновременно сложна, потому что из-за длительного отсутствия спецификации производители браузеров свободно расширяли BOM по своему усмотрению. Многие элементы, схожие в разных браузерах, стали стандартами де-факто, которые соблюдаются и по сей день из соображений взаимной совместимости. Чтобы стандартизировать эти фундаментальные аспекты JavaScript, консорциум W3C определил основные BOM-элементы в спецификации HTML5.


    Объектная модель документа, или «DOM», является программным интерфейсом доступа к элементам веб-страниц. По сути, это API страницы, позволяющий читать и манипулировать содержимым, структурой и стилями страницы. Давайте разберемся как это устроено и как это работает.

    Как строится веб-страница?

    Процесс преобразования исходного HTML-документа в отображаемую стилизованную и интерактивную страницу, называется “Critical Rendering Path”(“Критическим путем рендеринга”). Хотя этот процесс можно разбить на несколько этапов, как я описал это в статье «Понимание критического пути рендеринга », эти этапы можно условно сгруппировать в два этапа. В первом браузер анализирует документ, чтобы определить, что в конечном итоге будет отображаться на странице, а во второй браузер выполняет рендеринг.

    Результатом первого этапа является то, что называется “render tree”(«дерево рендеринга»). Дерево рендеринга – это представление элементов HTML, которые будут отображаться на странице, и связанных с ними стилей. Чтобы построить это дерево, браузеру нужны две вещи:

  • CSSOM, представление стилей, связанных с элементами
  • DOM, представление элементов
  • Из чего состоит DOM?

    DOM – это объектное представление исходного HTML-документа. Он имеет некоторые различия, как мы увидим ниже, но по сути это попытка преобразовать структуру и содержание документа HTML в объектную модель, которая может использоваться различными программами.

    Структура объектов DOM представлена тем, что называется «деревом узлов». Оно так называется, потому что его можно рассматривать как дерево с одним родительским элементом, который разветвляется на несколько дочерних ветвей, каждая из которых может иметь листья. В этом случае родительский «элемент» – это корневой элемент, дочерние «ветви» – это вложенные элементы, а «листья» – это содержимое внутри элементов.

    Давайте рассмотрим этот HTML-документ в качестве примера:

    My first web page Hello, world!

    How are you?

    Этот документ может быть представлен в виде следующего дерева узлов:

    • html
      • head
        • title
          • My first web page
      • body
        • h1
          • Hello, world!
        • p
          • How are you?
    Чем DOM не является

    В приведенном выше примере кажется, что 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!
      2. Когда DOM модифицируется кодом Javascript

      Помимо того, что 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!

      How are you?

      DOM будет включать элемент

      • html
        • head
        • body
          • h1
            • Hello, world!
          • p
            • How are you?

      Однако дерево рендеринга и, следовательно, то, что видно в окне просмотра, не будет включено в этот элемент.

      • html
        • body
          • h1
            • Hello, world!
      DOM – это не то, что отображается в DevTools

      Это различие немного меньше, потому что инспектор элементов DevTools обеспечивает самое близкое приближение к DOM, которое мы имеем в браузере. Однако инспектор DevTools содержит дополнительную информацию, которой нет в DOM.

      Лучший пример этого – псевдоэлементы CSS. Псевдоэлементы, созданные с использованием селекторов ::before и ::after , являются частью CSSOM и дерева рендеринга, но технически не являются частью DOM. Это связано с тем, что DOM создается только из исходного HTML-документа, не включая стили, примененные к элементу.

      Несмотря на то, что псевдоэлементы не являются частью DOM, они есть в нашем инспекторе элементов devtools.


      Резюме

      DOM – это интерфейс к HTML-документу. Он используется браузерами как первый шаг к определению того, что визуализировать в окне просмотра, и кодом Javascript для изменения содержимого, структуры или стиля страницы.

    innerHTML
    var text = element.innerHTML;
    element.innerHTML = "";
    Присвоение нового innerHTML осуществляет перезапись кода, даже если новое значение добавлено к текущему (+=). Скрипты, добавленные таким образом, не выполняются.

    outerHTML
    Содержит элемент целиком, изменить его невозможно. Технически при записи в это свойство создается новый элемент, который заменяет старый. Ссылки на старый элемент в переменных не изменяются.

    data
    textNode.data — содержимое текстовых узлов и комментариев

    textContent
    element.textContent — текст внутри элемента без тегов.
    Существует также нестандартное свойство innerText , имеющее с textContent много общего.

    Видимость элемента

    hidden
    element.hidden = true
    Атрибут hidden не поддерживается в IE11.

    Атрибуты

    Большинство стандартных атрибутов в DOM становятся свойствами объекта:
    element.id = "id"
    Для нестандартных атрибутов свойство не создается (undefined)

    Можно создавать собственные DOM-свойства:
    element.myData = {name:"John", lastName:"Smith"};
    и методы:
    element.myFunc = function(){alert this.nodeName};
    Это работает, потому что узлы DOM являются обычными JavaScript-объектами. Такие нестандартные свойства и методы не влияют на отображение тега и видны только в JavaScript.

    Доступ к атрибутам тегов:
    element.hasAttribute(name)
    element.getAttribute(name)
    element.setAttribute(name, value)
    element.removeAttribute(name)
    element.attributes — псевдомассив атрибутов.

    Атрибуты нечувствительны к регистру (html), а свойства чувствительны (javaScript).
    Значение атрибута — всегда строка.

    Атрибут: a.getAttribute("href") — отображает именно то, что в HTML
    Свойство: a.href — может отличать от значения атрибута
    Чаще всего свойство зависит от атрибута, но не наоборот. Изменение свойства не влияет на аттрибут.

    Работа с классами

    Атрибуту class соответствуют два свойства:
    className — строка
    classList — объект

    методы объекта classList:
    element.classList.contains("class") — проверка, содержит ли объект данный класс
    element.classList.add("class")
    element.classList.remove("class")
    element.classList.toggle("class")

    classList является псевдомассивом, его можно перебирать через цикл for .

    data-атрибуты

    Пользовательские data -атрибуты доступны не только как атрибуты, но и через свойство dataset
    data-about = "some value"
    element.dataset.about

    Порядок узлов

    parent.contains(child) — true или false
    проверяет, является ли узел child вложенным в parent

    nodeA.compareDocumentPosition(nodeB) — предоставляет информацию о содержании и относительном порядке элементов. Возвращаемое значение — побитовая маска:

    Добавление и удаление узлов

    var div = document.createElement("div")
    document.createTextNode("text")

    parent.appendChild(element) — элемент добавляется в конец родителя
    parent.insertBefore(element, nextSibling) — элемент добавляется перед nextSibling
    parent.insertBefore(element, parent.firstChild) — добавляется в начало
    parent.insertBefore(element, null) — сработает как appendChild
    Все методы вставки возвращают вставленный узел.
    При перемещении элемента не нужно его предварительно удалять со старого места, метода вставки делают это автоматически.

    element.insertAdjacentHTML(where, html) — вставка произвольного HTML-кода в любое место документа. Where указывает куда следует вставить html по отношению к element — beforeBegin, afterBegin, beforeEnd, afterEnd.
    element.insertAdjacentElement(where, newElement)
    element.insertAdjacentText(where, text)
    два последних метода не поддерживаются в Firefox

    node.append(...nodes) – вставляет nodes в конец node ,
    node.prepend(...nodes) – вставляет nodes в начало node ,
    node.after(...nodes) – вставляет nodes после узла node ,
    node.before(...nodes) – вставляет nodes перед узлом node ,
    node.replaceWith(...nodes) – вставляет nodes вместо node .
    здесь nodes — это узлы или строки, в любых количествах и сочетаниях, перечисленные через запятую.

    var fragment = document.createDocumentFragment() — имитация DOM-узла, который при вставке в документ исчезает, оставляя только своих потомков. В современных браузерах не рекомендуется.

    element.cloneNode(true) — глубокая копия элемента
    element.cloneNode(false) — копия без дочерних элементов

    parent.removeChild(element)
    parent.replaceChild(newElement, element)
    element.remove() — удаляет элемент напрямую, без ссылки на родителя.
    Методы возвращают удаленный узел

    Понравилось? Лайкни нас на Facebook