简体   繁体   English

重新排序 dom 中的 html 元素

[英]Reorder html elements in dom

I have a list of elements:我有一个元素列表:

<div class="wrapper">
    <div class="abc"></div>
    <div class="abc"></div>
    <div class="abc"></div>
</div>

And I have an array or numbers which represent new order:我有一个代表新订单的数组或数字:

var arr = [2,1,0];

I would like to reposition these abc divs to new positions inside parent wrapper.我想将这些 abc div 重新定位到父包装器内的新位置。

Important thing is that abc divs have events and data attached to them and this needs to be preserved!重要的是 abc div 附加了事件和数据,这需要保留!

I have came up with this and it seems to be working as expected:我想出了这个,它似乎按预期工作:

var wrapper = $('.wrapper'), items = wrapper.children('div.abc');

var orderedItems = $.map(arr, function(value) {
    return $(items).clone(true,true).get(value);
});
wrapper.empty().html(orderedItems);

I wanted to make sure this is the right way.我想确保这是正确的方法。

I could do with javascript solution as well if possible.如果可能的话,我也可以使用 javascript 解决方案。

no need to copy all items .. twice 无需复制所有项目..两次

var wrapper = $('.wrapper'), 
    items = wrapper.children('.abc'),
    arr = [2,1,0];

//items.detach(); if arr doesn't reuse all items
wrapper.append( $.map(arr, function(v){ return items[v] }) );

If you want a pure Javascript solution (no jQuery involved) 如果你想要一个纯粹的Javascript解决方案(不涉及jQuery)

var arr = [2,1,0];
var wrapper = document.getElementsByClassName("wrapper");
var items = wrapper[0].children;
var elements = document.createDocumentFragment();

arr.forEach(function(idx) {
    elements.appendChild(items[idx].cloneNode(true));
});

wrapper[0].innerHTML = null;
wrapper[0].appendChild(elements);

A little improvement of my previous answer. 我之前的答案略有改进。 Fiddle: https://jsfiddle.net/jltorresm/1ukhzbg2/2/ 小提琴: https//jsfiddle.net/jltorresm/1ukhzbg2/2/

I know this is an old question, but google lead me to it. 我知道这是一个老问题,但谷歌引导我。 There is a sub property on flexbox (css) called 'order', that allow you to choose the order that elements are displayed. flexbox(css)上有一个名为'order'的子属性,允许您选择元素的显示顺序。 Is possible to use javascript to change this sub property and reorder the displayed elements. 可以使用javascript更改此子属性并重新排序显示的元素。

https://www.w3schools.com/cssref/css3_pr_order.asp https://www.w3schools.com/cssref/css3_pr_order.asp

Edit 1 - code example: 编辑1 - 代码示例:

<style>
 .wrapper {
   display: flex;
   flex-flow: column;
 }
</style>

<div class="wrapper">
  <div class="abc">One</div>
  <div class="abc">Tow</div>
  <div class="abc">Three</div>
</div>
<button id="reorder" type="button">Reorder</button>
<button id="unreorder" type="button">Unreorder</button>

<script>
var reorderButton = document.querySelector('#reorder');
var unreorderButton = document.querySelector('#unreorder');
var abcDivs = document.querySelectorAll('.abc');
var newOrder = [2, 1, 0];

reorderButton.addEventListener('click', function() {
  abcDivs.forEach(function(element, index) {
    element.style.order = newOrder[index];
  });
});
unreorderButton.addEventListener('click', function() {
  abcDivs.forEach(function(element, index) {
    element.style.order = null;
  });
});
</script>

Keep in mind that when you add an element that is already in the DOM, this element will be moved, not copied. 请记住,当您添加DOM中已有的元素时,此元素将被移动,而不是被复制。

CodePen CodePen

 let wrapper=document.querySelector(".wrapper"); let children=wrapper.children; let newOrder=[3,2,1,0]; //it means that the first element you want it to be the four element //The second element you want it to be the third //the third element you want it to be the second //the four element you want it to be the first for(let i=0;i<newOrder.length;i++){ for(let j=0;j<newOrder.length;j++){ if(i==newOrder[j]){ wrapper.appendChild(children[j]); break; } } } 
 <div class="wrapper"> <div>a</div> <div>b</div> <div>c</div> <div>d</div> </div> 

This solution works better for me, we build an array of elements ( [...wrapper.children] ) then we use .sort based on a model ([5,4,3,2,1,0]) and then we use appendChild. 这个解决方案对我来说效果更好,我们构建一个元素数组( [...wrapper.children] )然后我们使用.sort基于模型([5,4,3,2,1,0])然后我们使用appendChild。 Since the elements are the same as the originals, the event listeners remain working fine. 由于元素与原始元素相同,因此事件侦听器仍然可以正常工作。 Here the code: 这里的代码:

 //this is just to add event listeners [...document.getElementsByClassName("abc")].forEach(e => e.addEventListener("click", ev => console.log(ev.target.innerText)) ); var wrapper = document.getElementsByClassName("wrapper")[0]; var items = [...wrapper.children]; const newOrder = [5,4,3,2,1,0] items.sort((a, b)=>newOrder.indexOf(items.indexOf(a)) - newOrder.indexOf(items.indexOf(b))); items.forEach(it=>wrapper.appendChild(it)); 
 <div class="wrapper"> <div class="abc">0</div> <div class="abc">1</div> <div class="abc">2</div> <div class="abc">3</div> <div class="abc">4</div> <div class="abc">5</div> </div> 

As you can see, if you click on 0, 1, etc, the event listener works. 如您所见,如果您单击0,1等,则事件侦听器可以正常工作。

After reading through the others' solutions, I've created a simple bit of code to reverse elements such as div s or or li s that are wrapped in a single container element.在阅读了其他人的解决方案后,我创建了一段简单的代码来反转包含在单个容器元素中的元素,例如div或或li

// Select all divs which need to be reordered
const items = document.querySelectorAll("#plan-carousel .plans-carousel .column-holder")
// Create an array of the divs and reverse them
const reverseItems = Array.from(items).reverse()
// Select the parent or wrapper element
const wrapper = document.querySelector("#plan-carousel .plans-carousel")
// Iterate over the reversed array and append each one to the parent element
reverseItems.forEach(item => wrapper.appendChild(item))

References:参考:

  1. According to the MDN's appendChild() article : If the given child is a reference to an existing node in the document, appendChild() moves it from its current position to the new position.根据MDN 的appendChild()文章:如果给定的子节点是对文档中现有节点的引用,则 appendChild() 将其从当前的 position 移动到新的 position。

In other words, since these items already exist, when we append them they are simply moved rather than duplicated.换句话说,由于这些项目已经存在,当我们 append 时,它们只是被移动而不是复制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM