ReplaceChild: примеры (JAVASCRIPT)

Работа с DOM: замена дочерних элементов через replaceChild
Раздел: DOM, Манипуляции
replaceChild(newChild: Node, oldChild: Node): Node

Описание метода replaceChild

Метод replaceChild() является частью DOM API и предназначен для работы с древовидной структурой документа. Он используется для замены одного дочернего узла на другой внутри указанного родительского элемента. Операция происходит непосредственно в DOM, что приводит к мгновенному изменению отображения страницы.

Использование: Основное применение — динамическое обновление содержимого веб-страницы без её полной перезагрузки. Это может быть полезно для обновления элементов интерфейса, отображения новых данных или изменения структуры списков.

Синтаксис и аргументы: Метод вызывается у родительского узла и принимает два обязательных аргумента:

  • newNode (обязательный): DOM-узел, который требуется вставить. Это может быть элемент, текстовый узел или комментарий.
  • oldNode (обязательный): Существующий дочерний узел, который будет заменён. Этот узел должен быть непосредственным потомком родительского элемента.

Возвращаемое значение: Метод возвращает заменённый (oldNode) DOM-узел. Если замена прошла успешно, этот узел остаётся в памяти, но больше не является частью DOM-дерева. В случае ошибки (например, если oldNode не является дочерним) генерируется исключение DOMException.

Базовые примеры использования

Пример 1: Замена одного элемента на другой.

// HTML: <div id="parent"><span id="old">Старый текст</span></div>
const parent = document.getElementById('parent');
const oldNode = document.getElementById('old');
const newNode = document.createElement('p');
newNode.textContent = 'Новый параграф';
const replacedNode = parent.replaceChild(newNode, oldNode);
console.log(replacedNode.id); // 'old'
// Результат в DOM:
// <div id="parent"><p>Новый параграф</p></div>
// В консоли: old

Пример 2: Замена текстового узла.

// HTML: <div id="container">Исходный текст</div>
const container = document.getElementById('container');
const oldText = container.firstChild; // Получаем текстовый узел
const newText = document.createTextNode('Обновлённый текст');
container.replaceChild(newText, oldText);
// Результат:
// <div id="container">Обновлённый текст</div>

Пример 3: Попытка замены с некорректным старым узлом.

const parent = document.createElement('div');
const fakeOldNode = document.createElement('span');
const newNode = document.createElement('p');
try {
    parent.replaceChild(newNode, fakeOldNode);
} catch (e) {
    console.error(e.name); // DOMException
}
// Результат в консоли:
// NotFoundError

Похожие методы в JavaScript

1. Element.replaceWith() — более современный метод, позволяющий заменить узел одним или несколькими новыми узлами. Не требует обращения к родительскому элементу. Вызывается непосредственно на заменяемом узле.

2. Внутренние свойства: innerHTML и outerHTML — обеспечивают быструю замену содержимого или всего элемента через строки HTML. Менее производительны при частых операциях, но удобны для простой вставки разметки.

3. Node.replaceChild() vs Element.replaceWith(): replaceChild работает с любыми узлами и требует указания родителя. replaceWith работает только с элементами и текстовыми узлами, но его синтаксис проще. Для современных проектов часто предпочтительнее replaceWith.

Распространённые ошибки

1. Старый узел не является прямым потомком. Метод требует, чтобы oldNode был непосредственным дочерним элементом родителя, у которого вызывается метод.

const parent = document.createElement('div');
const child = document.createElement('span');
const grandChild = document.createElement('b');
child.appendChild(grandChild);
parent.appendChild(child);
// Попытка заменить grandChild, обращаясь к parent
const newNode = document.createElement('i');
// Это вызовет ошибку:
// parent.replaceChild(newNode, grandChild);

2. Передача несуществующих или null-узлов. Оба аргумента должны быть валидными узлами.

const parent = document.createElement('div');
// Вызовет TypeError:
// parent.replaceChild(null, null);

3. Использование узла из другого документа. Узлы должны принадлежать одному документу (или быть созданы через document.createElement).

const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const otherDoc = iframe.contentDocument;
const nodeFromOtherDoc = otherDoc.createElement('span');
const parent = document.createElement('div');
// Вызовет ошибку:
// parent.replaceChild(nodeFromOtherDoc, parent.firstChild);

Изменения и современные стандарты

Метод replaceChild существует с ранних версий DOM Level 1 и не претерпел значительных синтаксических изменений. Однако, с появлением Living Standard DOM, акцент сместился на более новые методы, такие как replaceWith, before, after. Эти методы предлагают более удобный и читаемый API для манипуляций с узлами.

Важным аспектом является поддержка: replaceChild поддерживается всеми браузерами полностью, в то время как replaceWith не работает в Internet Explorer. Для кросс-браузерной совместимости в legacy-проектах по-прежнему используют replaceChild.

Расширенные и специализированные примеры

Пример 1: Замена с использованием DocumentFragment. Эффективная массовая вставка узлов перед заменой.

Пример javascript
const list = document.getElementById('myList');
const oldItem = list.children[1]; // Элемент для замены
const fragment = document.createDocumentFragment();
['A', 'B', 'C'].forEach(text => {
    const li = document.createElement('li');
    li.textContent = text;
    fragment.appendChild(li);
});
// Создаём контейнер для фрагмента
const container = document.createElement('div');
container.appendChild(fragment);
// Заменяем старый элемент на содержимое контейнера
list.replaceChild(container, oldItem);
// Теперь container стал дочерним, а fragment вставлен
// При необходимости можно распаковать:
while (container.firstChild) {
    list.insertBefore(container.firstChild, container);
}
list.removeChild(container);

Пример 2: Перемещение существующего узла с помощью replaceChild. Метод может перемещать узел внутри документа.

Пример javascript
// HTML: <div id="source"><p>Элемент</p></div>
//        <div id="target"><span>Цель</span></div>
const source = document.getElementById('source');
const target = document.getElementById('target');
const p = source.querySelector('p');
const span = target.querySelector('span');
// Перемещаем параграф, заменяя им span в другом родителе
target.replaceChild(p, span);
// Теперь p является дочерним элементом target
// Результат DOM:
// <div id="source"></div>
// <div id="target"><p>Элемент</p></div>

Пример 3: Обработка событий и replaceChild. События, назначенные на старый узел, после замены не сохраняются на новом.

Пример javascript
const btn = document.createElement('button');
btn.textContent = 'Старая кнопка';
btn.addEventListener('click', () => alert('Старая'));
document.body.appendChild(btn);
const newBtn = document.createElement('button');
newBtn.textContent = 'Новая кнопка';
// Замена: старая кнопка удаляется вместе со слушателем
document.body.replaceChild(newBtn, btn);
// Клик по newBtn не вызовет alert

Аналоги в других языках программирования

PHP (DOMDocument): Класс DOMNode имеет метод replaceChild, аналогичный по логике.

$dom = new DOMDocument();
$dom->loadHTML('<div><span>Old</span></div>');
$parent = $dom->getElementsByTagName('div')[0];
$old = $parent->getElementsByTagName('span')[0];
$new = $dom->createElement('p', 'New');
$replaced = $parent->replaceChild($new, $old);
echo $dom->saveHTML();
// Результат: <div><p>New</p></div>

Python (xml.dom): Модуль предоставляет аналогичный интерфейс.

from xml.dom import minidom
dom = minidom.parseString('<div><span>Old</span></div>')
parent = dom.getElementsByTagName('div')[0]
old = parent.getElementsByTagName('span')[0]
new_elem = dom.createElement('p')
new_elem.appendChild(dom.createTextNode('New'))
parent.replaceChild(new_elem, old)
print(parent.toxml())
// Результат: <div><p>New</p></div>

Отличия: В JavaScript метод работает в среде браузера и напрямую влияет на отображаемую страницу. В серверных языках (PHP, Python) операции с DOM обычно предназначены для обработки XML/HTML-документов перед их отправкой клиенту.

JS replaceChild function comments

En
ReplaceChild Replaces a child node within the parent node with another node.