Создание, вставка и удаление элементов в JavaScript
На этом уроке мы научимся создавать узлы-элементы (createElement
) и текстовые узлы (createTextNode
). А также рассмотрим методы, предназначенные для добавления узлов к дереву (appendChild
, insertBefore
) и для удаления узлов из дерева (removeChild
).
Создания элементов и текстовых узлов
Создание элемента в JavaScript выполняется с помощью метода createElement
:
// $elem – переменная, в которую сохраним созданный элемент const $elem = document.createElement('tag');
Вместо tag
необходимо указать тег того элемента, который нужно создать.
Например, создадим элемент p:
const $elem = document.createElement('p');
Создание текстового узла в JavaScript осуществляется посредством метода createTextNode
:
const text = document.createTextNode('text');
В аргументе createTextNode
необходимо поместить текст, который должен иметь этот текстовый узел.
Например, создадим текстовый узел с текстом «Я новый текстовый узел»:
const text = document.createTextNode('Я новый текстовый узел');
Вставка элементов и текстовых узлов
Чтобы созданный элемент (или текстовый узел) появился в нужном месте страницы его необходимо туда вставить.
Выполнить в JavaScript это можно посредством различных методов.
Одни из самых старых – appendChild
и insertBefore
.
appendChild
appendChild
предназначен для вставки узла в конец элемента (т.е. после последнего его дочернего узла) для которого этот метод вызывается:
// $elem – элемент, во внутрь которого после последнего его дочернего узла необходимо вставить узел $node $elem.appendChild($node);
В качестве результата этот метод возвращает добавленный на страницу узел.
Пример, в котором добавим новый <li>
в конец <ol>
:
<ol id="colors"> <li>Красный</li> <li>Оранжевый</li> <li>Жёлтый</li> <li>Зелёный</li> <li>Голубой</li> <li>Синий</li> </ol> <script> const $newLi = document.createElement('li'); $newLi.textContent = 'Фиолетовый'; const $colors = document.querySelector('#colors'); $colors.appendChild($newLi); </script>
insertBefore
insertBefore
предназначен для вставки узла node
перед nextSibling
в $elem
:
$elem.insertBefore(node, nextSibling);
Если в качестве nextSibling
передать null
, то данный метод вставит node
после последнего дочернего узла $elem
. Т.е. выполнит действия аналогично appendChild
.
В качестве результата метод insertBefore
возвращает вставленный узел.
Например, вставим новый элемент <li>
перед третьим:
<ol id="colors"> <li>Красный</li> <li>Оранжевый</li> <li>Зелёный</li> <li>Голубой</li> <li>Синий</li> <li>Фиолетовый</li> </ol> <script> const $newLi = document.createElement('li'); $newLi.textContent = 'Жёлтый'; const $colors = document.querySelector('#colors'); $colors.insertBefore($newLi, $colors.children[2]); </script>
Современные методы вставки и замены
В JavaScript имеются следующие современные методы для вставки элементов и строк:
node.append
– для добавления узлов или строк в конецnode
;node.prepend
– для вставки узлов или строк в началоnode
;node.before
– для вставки узлов или строк доnode
;node.after
– для вставки узлов или строк послеnode
.
Пример использования методов:
<div id="message"> <p>message...</p> </div> <script> const $message = document.querySelector('#message'); // вставим строку «before» перед $message $message.before('before'); // вставим строку «after» перед $message $message.after('after'); const $p1 = document.createElement('p'); $p1.textContent = 'prepend'; // вставим элемент $p1 в начало $message $message.prepend($p1); const $p2 = document.createElement('p'); $p2.textContent = 'append'; // вставим элемент $p2 в конец $message $message.append($p2); </script>
В результате:
before <div id="message"> <p>prepend</p> <p>message...</p> <p>append</p> </div> after
InsertAdjacent
В JavaScript имеется набор методов insertAdjacent, которые позволяют вставить один или несколько узлов в указанную позицию position
относительно $elem
Всего существует 3 таких метода:
$elem.insertAdjacentElement(position, element)
– для вставки элемента (element
);$elem.insertAdjacentHTML(position, htmlString)
– для вставки строки (htmlString
) как HTML;- $elem.insertAdjacentText(position, string) – для вставки строки (
string
);
Значение position
, может быть, одним из следующих:
'beforebegin'
– непосредственно перед$elem
;'afterbegin'
– перед первым дочерним узлом$elem
;'beforeend'
– после последнего дочернего узла$elem
;'afterend'
– сразу после$elem
;
Пример использования insertAdjacentHTML
:
<ul id="list"> <li>CSS</li> </ul> <script> const $list = document.querySelector('#list'); $list.insertAdjacentHTML('beforebegin', '<h2>Веб-технологии</h2>'); $list.insertAdjacentHTML('afterbegin', '<li>HTML</li>'); $list.insertAdjacentHTML('beforeend', '<li>JavaScript</li>'); $list.insertAdjacentHTML('afterend', '<p>Для фронтенд разработчиков</p>'); </script>
Результат:
<h2>Веб-технологии</h2> <!-- beforebegin -->
<ul id="list"> <!-- целевой элемент -->
<li>HTML</li> <!-- afterbegin -->
<li>CSS</li>
<li>JavaScript</li> <!-- beforeend -->
</ul>
<p>Для фронтенд разработчиков</p> <!-- afterend -->
DocumentFragment
DocumentFragment
– это облегчённая версия Document
. Он используется в качестве обёртки для временного хранения HTML элементов.
После формирования фрагмента его можно использовать в различных методах (например, append
, prepend
и др.). При этом, когда мы его вставляем, то вставляется только его содержимое.
DocumentFragment
в основном используется, когда необходимо вставить множество элементов на страницу, а также для элемента <template>
.
Например, переместим все четные <li>
в новый <ul>
:
<ul id="source-list"> <li>One</li> <li>Two</li> <li>Three</li> <li>Four</li> </ul> <ul id="target-list"></ul> <script> const $evenLi = document.querySelectorAll('#source-list li:nth-child(even)'); // создадим пустой фрагмент let $fragment = new DocumentFragment(); $evenLi.forEach(($li) => { // добавим в фрагмент элемент $li $fragment.appendChild($li); }); // вставим фрагмент в #target-list document.querySelector('#target-list').appendChild($fragment); </script>
Ещё один пример, в котором добавим в <ul>
десять <li>
:
<ul id="list"></ul> <script> const $list = document.querySelector('#list'); // создадим пустой фрагмент let $fragment = new DocumentFragment(); for(let i = 0; i < 10; i++) { const $li = document.createElement('li'); $li.textContent = 'item-' + i; // добавим в фрагмент элемент $li $fragment.appendChild($li); } // вставим фрагмент в #target-list document.querySelector('#list').append($fragment); </script>
Использование DocumentFragment
в подобных сценариях может значительно ускорить ваш сайт. Т.к. изменение DOM — это очень затратная операция. А с помощью DocumentFragment
это можно сделать всего за одну операцию.
DocumentFragment
не является частью видимой DOM. Изменения, внесенные во фрагмент, не влияют на документ и производительность страницы.
При использовании современных методов для вставки элементов можно не использовать DocumentFragment
, т.к. в отличие от appendChild
и insertBefore
они позволяют вставлять сразу массив элементов.
Например, перепишем первый пример с использованием append
:
<ul id="source-list"> <li>One</li> <li>Two</li> <li>Three</li> <li>Four</li> </ul> <ul id="target-list"></ul> <script> const $evenLi = document.querySelectorAll('#source-list li:nth-child(even)'); // создадим пустой массив let $list = []; $evenLi.forEach(($li) => { // добавим в массив $target элемент $li $list.appendChild($li); }); // вставим массив элементов в #target-list document.querySelector('#target-list').append(...$list); </script>
Замена и клонирование узлов
Замену одних узлов другими в JavaScript можно выполнить с помощью методов replaceChild
(когда нужна поддержка «старых» браузеров) и replaceWith
.
replaceChild
replaceChild
предназначен для замены одного дочернего узла parentNode
другим:
parentNode.replaceChild(newChild, oldChild);
Где:
newChild
– элемент, которым необходимо заменитьoldChild
;parentNode
– родительский узел по отношениюoldChild
.
В качестве результата данный метод возвращает узел, который был заменён новым узлом, т.е. oldChild
.
Например, заменим в <ul> второй <li> на новый с текстом «Five».
<ul id="list"> <li>One</li> <li>Two</li> <li>Three</li> </ul> <script> $two = document.querySelector('#list li:nth-child(2)'); // создадим новый элемент $newLi = document.createElement('li'); $newLi.textContent = 'Five'; // заменим $two на $newLi $two.parentNode.replaceChild($newLi, $two); </script>
replaceWith
node.replaceWith
позволяет node заменить заданными узлами или строками:
node.replaceWith(...nodes, strings)
Например, заменим в <ul> второй <li> другими элементами:
<ul id="list"> <li>One</li> <li>Two</li> <li>Three</li> </ul> <script> $two = document.querySelector('#list li:nth-child(2)'); // создадим новые элементы $newLi1 = document.createElement('li'); $newLi1.textContent = 'Five'; $newLi2 = document.createElement('li'); $newLi2.textContent = 'Six'; // заменим $two на $newLi1 и $newLi2 $two.replaceWith($newLi1, $newLi2); </script>
cloneNode – клонирование узла
cloneNode
предназначен для создания копии узла:
let copy = node.cloneNode(deep);
Где:
node
– узел, который нужно клонировать;copy
– переменная, в которую нужно поместить новый узел, который будет копиейnode
;deep
– глубина клонирования (по умолчаниюfalse
, т.е. выполняется клонирование только самого элементаnode
без детей); если установитьtrue
, тоnode
будет скопирован со всеми его детьми.
Например, скопируем <ul> и вставим её в конец <body>.
<ul id="list"> <li>One</li> ... </ul> <script> // выбираем #list const $list = document.querySelector('#list'); // клонируем $list и помещает его в $copy const $copy = $list.cloneNode(true); // вставляем $copy в конец <body> document.body.append($copy); </script>
Удаление узлов
Удалить узел из DOM можно в JavaScript с помощью методов removeChild
(считается устаревшим) и remove
.
removeChild
Синтаксис removeChild
:
parent.removeChild(node)
Для удаления узла необходимо вызвать метод removeChild
у родительского элемента и передать ему в качестве аргумента его сам (node
).
Например, удалим второй <li>
в <ol>
:
<ol id="devices"> <li>Смартфон</li> <li>Планшет</li> <li>Ноутбук</li> </ol> <script> const $liSecond = document.querySelector('#devices li:nth-child(2)'); // вызываем у родительского элемента метод removeChild и передаём ему в качестве аргумента узел который нужно удалить $liSecond.parentNode.removeChild($liSecond); </script>
В качестве результата метод removeChild
возвращает удалённый узел.
Например, удалим элемент, а затем вставим его в другое место:
<div id="message-1"> <p>...</p> </div> <div id="message-2"></div> <script> const $p = document.querySelector('#message-1>p'); // удалим элемент p const result = $p.parentElement.removeChild($p); // вставим удалённый элемент p в #message-2 document.querySelector('#message-2').append(result); </script>
remove
Ещё один способ удалить узел – это использовать метод remove
.
Синтаксис remove
:
node.remove()
Например, удалим элемент при нажатии на него:
<button>Кнопка</button> <script> document.querySelector('button').onclick = function() { // удалим элемент this.remove(); } </script>
Когда мы вставляем элементы, они удаляются со старых мест.
Задачи
1. Имеется два списка в документе. Необходимо переместить элементы из второго списка в первый.
2. Создать список, текстовое поле и 2 кнопки. Написать код на языке JavaScript, который в зависимости от нажатой кнопки добавляет текст, находящийся в текстовом поле, в начало или в конец списка.
3. Напишите функцию, удаляющую все текстовые узлы у элемента.
4. Имеется 2 списка (<ul>
...</ul>
), напишите код на языке JavaScript, удаляющий все элементы из 1 и 2 списка.
5. Удалить содержимое элемента, т.е. все его дочерние узлы
6. Заменить текстовый узел "Модель" текстовым узлом "Чертёж", который необходимо создать с помощью метода createTextNode().
<select id="myList"><li>Схема</li><li>Модель</li><li>Эскиз</li></select>
7. Поменяйте местами первый и последний дочерние узлы у списка ul с id="myList".
Я решил таким образом:
Набросал 4 различных способа (1 лучше не использовать, сделал для примера):
Ссылка на пример: modifying-document-task-01
Возможно, нужно немного исправить выше. Столкнулся с ошибкой в Хроме, не указав второй параметр.
чтобы прокрутить в цикле получить данные и подставить значение в тег списка в этом же теге снова передаю данные с помощью onchange той же функции js, где она должна так же отправить данные на сервер, получить ответ и создать следующий DOM элемент div с другим id вставив тег select>option и вывести следом за предыдущим в родительском элементе…
То есть при каждом возврате данных с сервера мне надо чтобы создавался DOM элемент, в него добавлялся тег или к примеру(в зависимости от типа поля).
itchief.ru/assets/uploadify/a/9/b/a9ba2d009d894505e538eb5f9440ac5b.png
При первом вызове этой функции все отрабатывает правильно, создает элемент, отображается в DOM структуре, при повторном попадании создает также элемент div присваивает ему id, но когда использую appendChild() ругается: Cannot read property 'appendChild' of null. Я как понимаю скрипт отрабатывается раньше загрузки разметки… Какими путями можно решить данную задачу?