Как переместить элемент в другой элемент?


1689

Я хотел бы переместить один элемент DIV в другой. Например, я хочу переместить это (включая всех детей):

<div id="source">
...
</div>

в это:

<div id="destination">
...
</div>

так что у меня так:

<div id="destination">
  <div id="source">
    ...
  </div>
</div>

21
Просто используйте $ (target_element) .append (to_be_inserted_element);
— Мохаммед Ариб Сиддики

2
Или: destination.appendChild (source) с использованием простого javascript
— Люк

мы можем достичь этого с помощью CSS? это возможно ?
— РаджКумар Самала

6
@RajKumarSamala CSS не может изменить структуру HTML, только его представление.
— Марк Ричман

Ответы:


39

Когда-нибудь пробовал простой JavaScript ... destination.appendChild(source);?

onclick = function(){ destination.appendChild(source); }
div{ margin: .1em; } 
#destination{ border: solid 1px red; }
#source {border: solid 1px gray; }
<!DOCTYPE html>
<html>

 <body>

  <div id="destination">
   ###
  </div>
  <div id="source">
   ***
  </div>

 </body>
</html>


* кто-то поставил перед глобальным событием onclick фрагмента демонстрации ключевое слово varв своей попытке улучшить пост - но это неправильно!
— Беким Бакай

6
Удивительно, как люди все еще думают, что jQuery равен JavaScript. Нет необходимости в jQuery в 2017 году, правда.
— nkkollaw

2
нет необходимости в jquery в 2017 году, но иногда это помогает использовать что-то более легкое и похожее для задач, которые вы делаете снова и снова в каждом отдельном проекте. Я использую Cash-Dom как простой способ прослушивания событий document.ready, window.load в кросс-браузерной форме. очень просто.
— eballeste

1
Меняя это на принятый ответ, теперь, когда наступил 2020 год :)
— Марк Ричман

1
Удивительно, как люди все еще думают, что jQuery равен JavaScript. В 2020 году больше нет необходимости в jQuery.
— ii iml0sto1

1794

Вы можете использовать appendToфункцию (которая добавляет в конец элемента):

$("#source").appendTo("#destination");

В качестве альтернативы вы можете использовать prependToфункцию (которая добавляет в начало элемента):

$("#source").prependTo("#destination");

Пример:


23
Предупреждение о том, что в jQuery mobile это может работать некорректно, поскольку вместо этого может быть создана другая копия элемента.
— Джордан Рейтер

32
appenTo создает копию или фактически перемещает весь div к месту назначения? (потому что, если он скопирует, он вызовет ошибки при вызове div по id)

50
Вот отличная статья об извлечении, замене и перемещении элементов в jQuery: elated.com/articles/jquery-removing-replacing-moving-elements
— xhh

42
Обратите внимание на документацию jQuery для appendTo, в которой говорится, что элемент перемещен: it will be moved into the target (not cloned) and a new set consisting of the inserted element is returned- api.jquery.com/appendto
— John K

15
Вы не двигаете это, просто добавляете. Ниже ответ делает правильное движение.
— Аарон

913

мое решение:

ШАГ:

jQuery("#NodesToMove").detach().appendTo('#DestinationContainerNode')

COPY:

jQuery("#NodesToMove").appendTo('#DestinationContainerNode')

Обратите внимание на использование .detach (). При копировании будьте осторожны, чтобы не дублировать идентификаторы.


86
Лучший ответ. Принятый ответ создает копию, но не перемещает элемент, как требует вопрос.
— paulscode

97
Извините, но принятый Эндрю Хэром правильный ответ - отсоединение не нужно. Попробуйте это в JSFiddle от Pixic выше - если вы удаляете вызовы detach, он работает точно так же, то есть выполняет перемещение, а не копию. Вот ответвление только с одним изменением: jsfiddle.net/D46y5 Как описано в API: api.jquery.com/appendTo : «Если элемент, выбранный таким образом, вставляется в одно место в другом месте в DOM, он будет перемещен в цель (не клонировано) и возвращается новый набор, состоящий из вставленного элемента "
— Джон - Не число

8
@ John-NotANumber прав - detach () здесь не нужен. Принятый ответ - лучший, вам просто нужно правильно прочитать документацию.
— Леонард Чаллис

11
В документации appendTo также говорится: «Если имеется более одного целевого элемента, однако, клонированные копии вставленного элемента будут созданы для каждой цели после первой, и этот новый набор (исходный элемент плюс клоны) будет возвращен». Так что в общем случае это решение МОЖЕТ также создавать копии!
— Винсент Пазеллер

Великий! Или вы можете использовать это, чтобы быть более точным в том, куда двигаться$('#nodeToMove').insertAfter('#insertAfterThisElement');
— Виктор Августо,

108

Я просто использовал:

$('#source').prependTo('#destination');

Который я схватил отсюда .


7
Ну, отсоединение полезно, когда вы хотите удержать элемент и вставить его позже, но в вашем примере вы все равно вставите его немедленно.
— Тим Бюте

1
Боюсь, я не совсем понимаю, к чему вы клоните, не могли бы вы предоставить пример кода?
— kjc26ster

1
Я имею в виду, prependTo, отсоединяет элемент от его исходного положения и вставляет его в новое. Функция detach, с другой стороны, просто отсоединяет выбранный элемент, и вы можете сохранить его в переменной, чтобы вставить его в DOM в более поздний момент времени. Дело в том, что ваш звонок отсоединения не нужен. Удалите его, и вы добьетесь того же эффекта.
— Тим Бют

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

96

Как насчет решения JavaScript ?

// Declare a fragment:
var fragment = document.createDocumentFragment();

// Append desired element to the fragment:
fragment.appendChild(document.getElementById('source'));

// Append fragment to desired element:
document.getElementById('destination').appendChild(fragment);

Проверьте это.


8
Зачем использовать createDocumentFragment вместо простого document.getElementById ('destination'). AppendChild (document.getElementById ('source'))?
— Гунар Гесснер

6
@ GunarC.Gessner, если вам нужно изменить исходный объект перед добавлением его к целевому объекту, тогда лучше всего использовать фрагмент, который является воображаемым объектом и не является частью дерева DOM, вы получаете лучшую производительность при изменении исходный объект, когда он был перемещен из своего исходного места (теперь он внутри фрагмента), а не изменяет его в своем первоначальном месте перед добавлением.
— Али Бассам

5
Я хочу добавить для актуальности предложения чистого JavaScript-решения. Не следует предполагать, что jQuery всегда используется
— Александр Фрадиани

1
Вопрос: При добавлении дочернего узла мы теряем вложенные события?
— Jimasun

1
Ответ на мой собственный вопрос - да, он сохраняет прикрепленные события.
— Jimasun

95

Если в том месте, divкуда вы хотите поместить свой элемент, есть содержимое, и вы хотите, чтобы элемент отображался после основного содержимого:

  $("#destination").append($("#source"));

Если в том месте, divкуда вы хотите поместить свой элемент, есть содержимое, и вы хотите показать элемент перед основным содержимым:

$("#destination").prepend($("#source"));

Если место, divкуда вы хотите поместить свой элемент, пусто или вы хотите заменить его полностью:

$("#element").html('<div id="source">...</div>');

Если вы хотите продублировать элемент перед любым из вышеперечисленных:

$("#destination").append($("#source").clone());
// etc.

Я нахожу все жирным шрифтом немного трудным для чтения, но это самый информативный ответ, так что он получает мое одобрение.
— Майкл Шепер

32

Ты можешь использовать:

Вставить после,

jQuery("#source").insertAfter("#destination");

Чтобы вставить внутрь другого элемента,

jQuery("#source").appendTo("#destination");

20

Если вам нужна быстрая демонстрация и более подробная информация о том, как вы перемещаете элементы, попробуйте эту ссылку:

http://html-tuts.com/move-div-in-another-div-with-jquery


Вот краткий пример:

Чтобы переместить элемент выше:

$('.whatToMove').insertBefore('.whereToMove');

Чтобы переместить ПОСЛЕ элемента:

$('.whatToMove').insertAfter('.whereToMove');

Чтобы переместиться внутрь элемента, НАД ВСЕМИ элементами внутри этого контейнера:

$('.whatToMove').prependTo('.whereToMove');

Чтобы переместиться внутрь элемента, ПОСЛЕ ВСЕХ элементов внутри этого контейнера:

$('.whatToMove').appendTo('.whereToMove');

19

Вы можете использовать следующий код для перемещения источника к месту назначения

 jQuery("#source")
       .detach()
       .appendTo('#destination');

попробуйте работать codepen


11

Старый вопрос, но он попал сюда, потому что мне нужно переместить контент из одного контейнера в другой, включая всех слушателей событий .

У jQuery нет способа сделать это, но есть стандартная функция DOM appendChild.

//assuming only one .source and one .target
$('.source').on('click',function(){console.log('I am clicked');});
$('.target')[0].appendChild($('.source')[0]);

Использование appendChild удаляет .source и помещает его в цель, включая его прослушиватели событий: https://developer.mozilla.org/en-US/docs/Web/API/Node.appendChild


6

Вы также можете попробовать:

$("#destination").html($("#source"))

Но это полностью перезапишет все, что у вас есть #destination.


2
И разбить слушателей событий на перемещенный элемент.
— Игорь Помаранский

4

Я заметил огромную утечку памяти и разницу в производительности между insertAfter& afterили insertBefore& before. Если у вас тонны DOM-элементов или вам нужно использовать after()или before()внутри события MouseMove , память браузера, вероятно, увеличится, и следующие операции будут выполняться очень медленно.

Решение, которое я только что испытал, состоит в том, чтобы вместо этого использовать insertBefore before()и insertAfter after().


Это похоже на проблему, связанную с реализацией движка JavaScript. В какой версии браузера и движке JS вы это видите?
— Марк Ричман

1
Я использую Chrome версии 36.0.1985.125 и использую jQuery v1.11.1. Я связываю функцию с событием mousemove, которая перемещает простой DIV вниз или вверх по элементу, над которым находится мышь. Следовательно, это событие и функция выполняются, пока вы перетаскиваете курсор. Утечка памяти происходит с помощью after () и before (), если вы перемещаете курсор на 30 секунд +, и исчезает, если я просто использую insertAfter & insertBefore.
— спецназ

1
Я бы открыл ошибку с Google на этом.
— Марк Ричман

2

Вы можете использовать чистый JavaScript, используя appendChild()метод ...

Метод appendChild () добавляет узел в качестве последнего дочернего элемента узла.

Совет. Если вы хотите создать новый абзац с текстом, не забудьте создать текст как узел текста, который вы добавляете к абзацу, а затем добавьте абзац в документ.

Вы также можете использовать этот метод для перемещения элемента из одного элемента в другой.

Совет: Используйте метод insertBefore () для вставки нового дочернего узла перед указанным существующим дочерним узлом.

Таким образом, вы можете сделать это, чтобы выполнить работу, это то, что я создал для вас, используя appendChild(), запустите и посмотрите, как это работает для вашего случая:

function appendIt() {
  var source = document.getElementById("source");
  document.getElementById("destination").appendChild(source);
}
#source {
  color: white;
  background: green;
  padding: 4px 8px;
}

#destination {
  color: white;
  background: red;
  padding: 4px 8px;
}

button {
  margin-top: 20px;
}
<div id="source">
  <p>Source</p>
</div>

<div id="destination">
  <p>Destination</p>
</div>

<button onclick="appendIt()">Move Element</button>


0

Для полноты картины есть другой подход wrap()или wrapAll()упомянутый в этой статье . Таким образом, вопрос OP мог бы быть решен с помощью этого (то есть, предполагая, что <div id="destination" />он еще не существует, следующий подход создаст такую ​​обертку с нуля - у OP не было ясности относительно того, существует ли обертка уже или нет):

$("#source").wrap('<div id="destination" />')
// or
$(".source").wrapAll('<div id="destination" />')

Это звучит многообещающе. Тем не менее, когда я пытался сделать $("[id^=row]").wrapAll("<fieldset></fieldset>")несколько вложенных структур, как это:

<div id="row1">
    <label>Name</label>
    <input ...>
</div>

Это правильно оборачивает те <div>...</div>и <input>...</input>НО ИНАЧЕ пропускает <label>...</label>. Поэтому я в конечном итоге использовал явное $("row1").append("#a_predefined_fieldset")вместо этого. Итак, YMMV.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.