Как заменить дочерние узлы DOM в JavaScript?
Какой самый простой способ поменять порядок дочерних узлов?
Например, я хочу, чтобы childNode[3] был childNode[4], и наоборот.
11 ответов
Нет необходимости в клонировании. Вы можете просто переместить один узел перед другим с помощью этого:
childNode[4].parentNode.insertBefore(childNode[4], childNode[3]);
Вы получаете родителя узла. Затем вы вызываете метод insertBefore для родительского элемента и передаете ему узел childNode[4] и говорите, что хотите вставить его до childNode[3]. Это даст вам результат обмена их ордером, поэтому 4 будут до 3, когда это будет сделано.
Справочная документация на insertBefore.
Любой узел, вставленный в DOM, который уже находится в DOM, сначала удаляется автоматически, а затем вставляется обратно, поэтому нет необходимости сначала его удалять вручную.
использование .before
или же .after
!
Это ванильный JS!
childNode[3].before(childNode[4]);
или же
childNode[4].after(childNode[3]);
Для большей долговременной замены попробуйте:
function swap(node1, node2) {
const afterNode2 = node2.nextElementSibling;
const parent = node2.parentNode;
node1.replaceWith(node2);
parent.insertBefore(node1, afterNode2);
}
Это должно работать, даже если родители не совпадают
Могу ли я использовать - 86% ноя 2018
Ответ от jfriend00 на самом деле не меняет местами элементы (он "меняет местами" только те элементы, которые находятся рядом друг с другом и только под одним родительским узлом). Это нормально, так как это был вопрос.
Этот пример меняет местами элементы путем клонирования, но независимо от их положения и уровня DOM:
// Note: Cloned copy of element1 will be returned to get a new reference back
function exchangeElements(element1, element2)
{
var clonedElement1 = element1.cloneNode(true);
var clonedElement2 = element2.cloneNode(true);
element2.parentNode.replaceChild(clonedElement1, element2);
element1.parentNode.replaceChild(clonedElement2, element1);
return clonedElement1;
}
Редактировать: Добавлен возврат новой ссылки (если вы хотите сохранить ссылку, например, для доступа к атрибуту parentNode (в противном случае он теряется)). Пример: e1 = exchangeElements(e1, e2);
Мне нужна была функция, чтобы поменять местами два произвольных узла, сохраняя замененные элементы в одном и том же месте в DOM. Например, если a находится в позиции 2 относительно своего родителя, а b находится в позиции 0 относительно своего родителя, b должен заменить позицию 2 предыдущего родителя a, а a должен заменить дочерний элемент 0 предыдущего родителя b.
Это моё решение, которое позволяет свопу находиться в совершенно разных частях дома. Обратите внимание, что обмен не может быть простым трехступенчатым обменом. Каждый из этих двух элементов должен быть удален из dom сначала, потому что у них могут быть родные братья, которые нуждаются в обновлении, и т.д.
Решение: я вставил два div-элемента держателя, чтобы удерживать место каждого узла, чтобы поддерживать относительный порядок родного брата. Затем я заново вставляю каждый из узлов в заполнитель другого, сохраняя относительное положение, которое было у замененного узла до замены. (Мое решение похоже на решение Бака).
function swapDom (a, b) {
var aParent = a.parentNode;
var bParent = b.parentNode;
var aHolder = document.createElement("div");
var bHolder = document.createElement("div");
aParent.replaceChild(aHolder,a);
bParent.replaceChild(bHolder,b);
aParent.replaceChild(b,aHolder);
bParent.replaceChild(a,bHolder);
}
Используйте фиктивного брата в качестве временного маркера положения, а затем
Он работает для любых братьев и сестер (не только соседних), а также поддерживает обработчики событий.
Точно так же, как временные переменные используются для обмена переменными, если отсутствуют более сложные методы.
Лучший способ сделать это — создать временный узел
function swapNodes(node1, node2) {
const temp = document.createComment('')
node2.replaceWith(temp)
node1.replaceWith(node2)
temp.replaceWith(node1)
}
Для реального обмена любых узлов без cloneNode:
<div id="d1">D1</div>
<div id="d2">D2</div>
<div id="d3">D3</div>
С функцией SwapNode (используя PrototypeJS):
function SwapNode(N1, N2) {
N1 = $(N1);
N2 = $(N2);
if (N1 && N2) {
var P1 = N1.parentNode;
var T1 = document.createElement("span");
P1.insertBefore(T1, N1);
var P2 = N2.parentNode;
var T2 = document.createElement("span");
P2.insertBefore(T2, N2);
P1.insertBefore(N2, T1);
P2.insertBefore(N1, T2);
P1.removeChild(T1);
P2.removeChild(T2);
}
}
SwapNode('d1', 'd2');
SwapNode('d2', 'd3');
Будет производить:
<div id="d3">D3</div>
<div id="d1">D1</div>
<div id="d2">D2</div>
Решение, которое работает без клонирования, учитывая индексы двух элементов для обмена:
function swapChildren(parentElement, index1, index2) {
if (index1 === index2)
return
if (index1 > index2) {
const temp = index1
index1 = index2
index2 = temp
}
const { [index1]: element1, [index2]: element2 } = parentElement.childNodes
if (index2 === index1 + 1) {
parentElement.insertBefore(element2, element1)
} else {
const reference = element2.nextSibling
parentElement.replaceChild(element2, element1)
parentElement.insertBefore(element1, reference)
}
}
Попробуйте этот метод:
Get the parent element
- Хранить
two elements you want to swap
Хранить
.nextSibling of the node that is last in order
Например: [1,2,3,4] => мы хотим поменять местами 3 и 2, а затем сохранить nextSibling 3, '4'..insertBefore (3,2);
- .insertBefore (2, NextSibling);
Вы можете поменять местами элемент DOM с его следующим братом следующим образом:
el.parentNode.insertBefore(el, el.nextElementSibling)
Или со своим предыдущим братом следующим образом:
el.parentNode.insertBefore(el, el.previousElementSibling)
И если ваш контент динамический, вы можете проверить, что
el.nextElementSibling
или же
el.previousElementSibling
не является нулевым.
Код Пояснение
- val иval2 - это 2 узла / элемента, которые нужно поменять местами
- Equiv(index) получает текущий узел / элемент в DOM по индексу, переданному как параметр
ПРИМЕЧАНИЕ: он будет считать комментарии и текстовые элементы, поэтому будьте осторожны xD
Надеюсь, это поможет:)
function equiv(index){
return Array.prototype.slice.call( document.querySelectorAll("*"))[index];
}
function swap (val,val2){
let _key = val.key;
let _key_ = val2.key;
_key_ = _key < _key_ ? _key_+1:_key_;
let _parent_ = val2.parentElement.valueOf();
if (val.parentElement.children.length ==1)
val.parentElement.appendChild(val2);
else
val.parentElement.insertBefore(val2,val);
if (_parent_.children.length ==0)
_parent_.appendChild(val);
else{
let _sibling_ = equiv(_key_);
_parent_.insertBefore(val,_sibling_);}
}