Как заменить дочерние узлы 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)
    }
}

Попробуйте этот метод:

  1. Get the parent element
  2. Хранить two elements you want to swap
  3. Хранить .nextSibling of the node that is last in orderНапример: [1,2,3,4] => мы хотим поменять местами 3 и 2, а затем сохранить nextSibling 3, '4'.

  4. .insertBefore (3,2);

  5. .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_);}
}
Другие вопросы по тегам