InsertBefore: примеры (JAVASCRIPT)
insertBefore(newNode: Node, referenceNode: Node): NodeОсновы метода insertBefore
Метод Node.insertBefore() принадлежит DOM API и используется для вставки указанного узла перед другим, уже существующим, дочерним узлом внутри заданного родительского элемента. Метод применяется для точного позиционирования нового элемента в структуре DOM относительно его будущих соседей.
Синтаксис:parentNode.insertBefore(newNode, referenceNode);
Аргументы:
- newNode (обязательный): Узел (элемент, текстовый узел, комментарий и т.д.), который требуется вставить.
- referenceNode (обязательный): Дочерний узел parentNode, перед которым произойдет вставка. Если имеет значение
null, новый узел добавляется в конец списка дочерних элементов родителя.
Возвращаемое значение: Метод возвращает вставленный узел (т.е. newNode). Если вставка по какой-то причине не удалась, возвращается null.
Метод изменяет DOM напрямую. Если вставляемый узел уже существует в DOM в другом месте, он будет сначала удален оттуда, а затем вставлен на новую позицию.
Примеры базового использования
Создание и вставка нового элемента перед конкретным соседом.
const list = document.getElementById('myList');
const newItem = document.createElement('li');
newItem.textContent = 'Новый пункт';
const secondItem = list.children[1]; // Второй элемент списка
list.insertBefore(newItem, secondItem);Было: <ul id="myList"><li>1</li><li>2</li><li>3</li></ul> Стало: <ul id="myList"><li>1</li><li>Новый пункт</li><li>2</li><li>3</li></ul>
Вставка в конец списка с помощью null в качестве второго аргумента.
const list = document.getElementById('myList');
const lastItem = document.createElement('li');
lastItem.textContent = 'Последний';
list.insertBefore(lastItem, null); // Аналог list.appendChild(lastItem);Было: <ul id="myList"><li>1</li><li>2</li></ul> Стало: <ul id="myList"><li>1</li><li>2</li><li>Последний</li></ul>
Вставка существующего узла (перемещение элемента).
const list = document.getElementById('myList');
const firstItem = list.firstElementChild;
const lastItem = list.lastElementChild;
// Перемещаем первый элемент перед последним
list.insertBefore(firstItem, lastItem);Было: <ul id="myList"><li>A</li><li>B</li><li>C</li></ul> Стало: <ul id="myList"><li>B</li><li>A</li><li>C</li></ul>
Альтернативные методы JavaScript
Node.appendChild(): Добавляет узел в конец списка дочерних элементов указанного родителя. Более простой способ добавления элемента, когда позиция не важна или требуется именно конец списка. parent.appendChild(newNode) эквивалентно parent.insertBefore(newNode, null).
Element.insertAdjacentElement(): Более гибкий метод, позволяющий вставить элемент относительно позиции вызывающего элемента. Принимает строку-позицию ('beforebegin', 'afterbegin', 'beforeend', 'afterend') и новый элемент. Позволяет вставлять элементы не только как дочерние, но и как соседние. Удобен, когда работа идет с одним целевым элементом.
Element.before() / Element.after(): Современные методы для вставки узлов или строк непосредственно перед или после вызывающего элемента в DOM. Работают на уровне соседей, а не родитель-ребенок, что делает синтаксис более интуитивным для простых операций.
Распространенные ошибки
1. Попытка вставки с неверной ссылкой на родительский узел. Родителем должен быть узел, который действительно содержит referenceNode.
const parent1 = document.getElementById('div1');
const parent2 = document.getElementById('div2');
const newEl = document.createElement('span');
const refEl = parent2.querySelector('.target');
// Ошибка: refEl не является дочерним элементом parent1
parent1.insertBefore(newEl, refEl); // DOMException2. Передача в качестве referenceNode узла, который не является прямым дочерним элементом указанного родителя.
const parent = document.getElementById('parent');
const newEl = document.createElement('span');
const deeplyNestedRef = parent.querySelector('.deep .target');
// Ошибка, если '.target' находится не на первом уровне вложенности в parent
parent.insertBefore(newEl, deeplyNestedRef); // DOMException3. Игнорирование того, что вставка существующего узла перемещает его.
const list = document.querySelector('#list1');
const otherList = document.querySelector('#list2');
const item = list.children[0];
// Элемент item будет удален из #list1 и вставлен в #list2
otherList.insertBefore(item, otherList.firstChild);Современные изменения и спецификация
Сам метод insertBefore() долгое время остается стабильным и соответствует спецификации DOM Living Standard. Существенных изменений в его поведении в последних версиях браузеров нет. Основная эволюция происходит вокруг появления новых, более удобных методов-аналогов, таких как before(), after(), append(), prepend(). Эти методы являются частью современного DOM API и предлагают более лаконичный синтаксис для манипуляций.
Рекомендуется использовать insertBefore() в сценариях, требующих максимальной кросс-браузерной совместимости или точной вставки относительно конкретного дочернего узла. Для современных проектов можно рассматривать альтернативы из семейства методов Element для улучшения читаемости кода.
Сложные и нестандартные примеры
Вставка DocumentFragment для эффективного добавления нескольких элементов.
const list = document.getElementById('myList');
const fragment = document.createDocumentFragment();
['Пункт A', 'Пункт B', 'Пункт C'].forEach(text => {
const li = document.createElement('li');
li.textContent = text;
fragment.appendChild(li);
});
// Вставка всего фрагмента за одну операцию рефлоу
list.insertBefore(fragment, list.children[2]);Было: <ul id="myList"><li>1</li><li>2</li><li>3</li></ul> Стало: <ul id="myList"><li>1</li><li>2</li><li>Пункт A</li><li>Пункт B</li><li>Пункт C</li><li>3</li></ul>
Сортировка элементов списка на месте с использованием insertBefore.
function sortList(list) {
const items = Array.from(list.children);
items.sort((a, b) => a.textContent.localeCompare(b.textContent));
// Очистка и пересборка в отсортированном порядке
items.forEach(item => {
list.insertBefore(item, null); // appendChild effect
});
}
// Вызов функции сортирует элементы <li> по алфавитуСоздание функции-аналога insertAfter, которой нет в нативном API.
function insertAfter(newNode, existingNode) {
const parent = existingNode.parentNode;
const nextSibling = existingNode.nextSibling;
return parent.insertBefore(newNode, nextSibling);
}
// Использование
const refEl = document.querySelector('.reference');
const newSpan = document.createElement('span');
insertAfter(newSpan, refEl); // Вставит newSpan сразу после refElВставка текстового узла или комментария.
const container = document.getElementById('content');
const comment = document.createComment(' Важное место ');
const textNode = document.createTextNode('Новый текст');
const target = container.firstElementChild;
container.insertBefore(comment, target);
container.insertBefore(textNode, target.nextSibling);Аналоги в других языках
Python (Beautiful Soup): Библиотека для парсинга HTML предоставляет методы insert_before() и insert_after() для объекта тега, работающие похожим образом.
from bs4 import BeautifulSoup
soup = BeautifulSoup('<ul><li>1</li></ul>', 'html.parser')
new_tag = soup.new_tag("li")
new_tag.string = "Новый"
target_li = soup.li
target_li.insert_before(new_tag)<ul><li>Новый</li><li>1</li></ul>
PHP (DOMDocument): Класс DOMNode имеет метод insertBefore() с идентичной JavaScript логикой.
$dom = new DOMDocument();
$dom->loadHTML('<ul><li>1</li></ul>');
$ul = $dom->getElementsByTagName('ul')[0];
$newLi = $dom->createElement('li', 'Новый');
$refLi = $dom->getElementsByTagName('li')[0];
$ul->insertBefore($newLi, $refLi);<ul><li>Новый</li><li>1</li></ul>
jQuery: Библиотека jQuery предлагает методы .before(), .after(), .insertBefore(), .insertAfter(), которые абстрагируют работу с DOM. Здесь $(newNode).insertBefore(target) вставляет newNode перед target.