如何通过订单号定位弹性项目?

How to target flex item by its order number?

我需要以编程方式在它们的容器中重新排列我的 flex 项目,但我似乎无法找到如何通过 order select 它们数字。问题是它们没有按 DOM 顺序显示,而是使用 order css 属性显示。

How do I rearrange them?

我的html:

<div id="container">
    <div style="order: 17"></div>
    <div style="order: 25"></div>
    <div style="order: 2"></div>
    <div style="order: 3"></div>
    // ...
</div>

基本上我需要这样做:

| A | B | C | D | E |
       +----------->
     <---+---+---+
result:
| A | C | D | E | B |

所以,我想到了一个稍微滥用 CSS3 选择器的想法,它似乎有效,但我想知道这是如何 合法 的。

document.querySelector('div[style*="order: 25;"]')

然后要交换两个项目,我需要这样做:

var t = document.querySelector('div[style*="order: 25;"]');
document.querySelector('div[style*="order: 26;"]').style.order = 25;
t.style.order = 26;

您可以根据计算的 order.

对弹性项目进行排序

请注意,如果两个弹性项目具有相同的 order,则应根据它们的 DOM 位置对其进行排序。也就是说,排序必须是稳定的。由于 [].sort 不一定稳定,我将使用 merge sort.

的自定义实现
var orderedChildren = mergeSort([].map.call(
  document.getElementById('container').children,
  function(child) {
    return [child, +getComputedStyle(child).order];
  }
)).map(function(pair) {
  return pair[0];
});
function mergeSort(arr) {
  var m = Math.floor(arr.length / 2);
  if(!m) return arr;
  var arr2 = mergeSort(arr.splice(m)),
      arr1 = mergeSort(arr.splice(0));
  while(arr1.length && arr2.length)
    arr.push((arr1[0][1] > arr2[0][1] ? arr2 : arr1).shift());
  return arr.concat(arr1, arr2);
}

var orderedChildren = mergeSort([].map.call(
  document.getElementById('container').children,
  function(child) {
    return [child, +getComputedStyle(child).order];
  }
)).map(function(pair) {
  return pair[0];
});
function mergeSort(arr) {
  var m = Math.floor(arr.length / 2);
  if(!m) return arr;
  var arr2 = mergeSort(arr.splice(m)),
      arr1 = mergeSort(arr.splice(0));
  while(arr1.length && arr2.length)
    arr.push((arr1[0][1] > arr2[0][1] ? arr2 : arr1).shift());
  return arr.concat(arr1, arr2);
}
for(var i=0; i<orderedChildren.length; ++i) {
  orderedChildren[i].textContent = i;
}
#container {
  display: flex;
  flex-wrap: wrap;
}
#container > div {
  border: 1px solid;
  padding: 5px;
}
<div id="container">
  <div style="order: 17"></div>
  <div style="order: 25"></div>
  <div style="order: 2"></div>
  <div style="order: 3"></div>
  <div style="order: 17"></div>
  <div style=""></div>
  <div style="order: -17"></div>
  <div style="order: 2"></div>
</div>
If the numbers are ordered, it means JS has iterated the flex items according to their <code>order</code> property.