【问题标题】:Reorder li items according to a variable/condition根据变量/条件对 li 项重新排序
【发布时间】:2019-01-24 04:57:15
【问题描述】:

我有一个清单如下:

<ul>
  <li>First</li>
  <li>Second</li>
  <li>Third</li>
  <li>Fourth</li>
  <li>Fifth</li>
</ul>

我想要的是根据不同的条件对列表进行排序。例如,如果变量state == "foo",我希望Fourth li 首先出现,Second li 最后出现,如下所示:

<ul>
  <li>Fourth</li>
  <li>First</li>
  <li>Third</li>
  <li>Fifth</li>
  <li>Second</li>
</ul>

如果state == "bar" 我希望列表以其他方式出现。

还要考虑到将来可能存在state 可能等于"baz""foobar" 的情况,每个都有自己的顺序。因此,为每个状态编写自定义条件不是一种选择。

我的想法是为每个状态维护一个有序数组,然后使用诸如 Mustache 或 Handlebars 之类的东西根据数组呈现列表。有没有更好的解决方案,也是未来的证明?

【问题讨论】:

  • 请分享条件
  • @brk state 变量的作用类似于条件。
  • 嘿@radiantshaw,只是为了让你知道我已经添加了一个没有jQuery的sn-p!

标签: javascript html css


【解决方案1】:

我会这样做:

  • 使用对象来存储不同的订单,
  • 使用.forEach() 遵循所选顺序以重新订购lis。

新的 sn-ps

  • 使用.map(),可以将'change' function 缩减为一行!

没有 jQuery(更轻!)

var original_list = document.querySelectorAll('#listToOrder li');
const orders = {
  def: [0, 1, 2, 3, 4],
  foo: [3, 0, 2, 4, 1],
  bar: [3, 2, 4, 1, 0],
  baz: [2, 4, 0, 3, 1]
}

document.querySelector('#selector').addEventListener('change', function() {
  document.querySelector('#listToOrder').innerHTML = orders[this.value].map(index => original_list[index].outerHTML).join('');
});
<ul id="listToOrder">
  <li>First</li>
  <li>Second</li>
  <li>Third</li>
  <li>Fourth</li>
  <li>Fifth</li>
</ul>
<label>Select order: </label>
<select id="selector">
  <option value="def">Default</option>
  <option value="foo">Foo</option>
  <option value="bar">Bar</option>
  <option value="baz">Baz</option>
</select>

使用 jQuery

var original_list = $('#listToOrder li');
const orders = {
  def: [0, 1, 2, 3, 4],
  foo: [3, 0, 2, 4, 1],
  bar: [3, 2, 4, 1, 0],
  baz: [2, 4, 0, 3, 1]
}

$('#selector').on('change', function() {
  $('#listToOrder').html(orders[this.value].map(index => original_list[index].outerHTML));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="listToOrder">
  <li>First</li>
  <li>Second</li>
  <li>Third</li>
  <li>Fourth</li>
  <li>Fifth</li>
</ul>
<label>Select order: </label>
<select id="selector">
  <option value="def">Default</option>
  <option value="foo">Foo</option>
  <option value="bar">Bar</option>
  <option value="baz">Baz</option>
</select>

老sn-p

我想不出更简单的方法……但.map() 是个好点子!

var original_list = $('#listToOrder li');
const orders = {
  def: [0, 1, 2, 3, 4],
  foo: [3, 0, 2, 4, 1],
  bar: [3, 2, 4, 1, 0],
  baz: [2, 4, 0, 3, 1]
}

$('#selector').on('change', function() {
  var lis = '';
  orders[this.value].forEach(function(i){
    lis += original_list[i].outerHTML;
  })
  $('#listToOrder').html(lis);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="listToOrder">
  <li>First</li>
  <li>Second</li>
  <li>Third</li>
  <li>Fourth</li>
  <li>Fifth</li>
</ul>
<label>Select order: </label>
<select id="selector">
  <option value="def">Default</option>
  <option value="foo">Foo</option>
  <option value="bar">Bar</option>
  <option value="baz">Baz</option>
</select>

【讨论】:

  • 我认为在你的解决方案中使用 Array.prototype.map() 会更有效
  • 奇怪的是 jQuery 的 html() 接受数组但文档从未提及它。
  • @radiantshaw 是的。 :) 但这也是有道理的,因为当一个节点有子节点时,它就像数组一样。
  • 字符串也是类数组元素。
  • 有关信息,我在仅 JavaScript 的 sn-p 中添加了 .join(''),因为它返回了带有尾随逗号的元素的 outerHTML。我选择了这个solution 来纠正这种行为。
【解决方案2】:

我建议使用 data 的常量和 states 对象的数组来给出适当的顺序。

states 中的dataOrder 键将保存索引data 数组的顺序:

const data = ['First', 'Second', 'Third', 'Fourth', 'Fifth'];
const states = [
  {
    state: 'foo',
    dataOrder: [0, 1, 2, 3]
  },
  {
    state: 'bar',
    dataOrder: [3, 2, 1, 0]
  }
];

注意:在模板视图中,您可以使用问题中所写的 Mustache 或 Handlebars

【讨论】:

  • 这也是我最初的想法。我正在等待比这更好的方法。否则,这就是我认为的答案。
  • 如果您不可避免地需要订购所有不同的states,这很好,但如果您只是尝试访问其中一个,那么数组可能不是最佳选择,因为您必须挖掘通过states数组查找订单。
  • @aug 非常好的评论。顺便说一下,在你的答案中发布一个对象是最好的方法! +1
  • 您的订单与我的一模一样,这有点有趣……(stackoverflow.com/a/51891366/5061000) 因为您添加了另一种方法。无论如何,@aug 得到了最好的方法。你应该已经用它创建了一个 sn-p,八月。
  • @TakitIsy 您说得对:已删除。购买是的,您可以看到需要对您的答案进行很好的重构;)
【解决方案3】:

可能最好的选择是只维护一个映射到订单的州地图。

const statesOrder = {
  'foo':  [0, 1, 2, 3],
  'baz': [2, 1, 3, 0],
   ...
}

然后通过传入state来访问订单。

const listOrder = statesOrder[state];

另外别忘了,如果您只需要以视觉方式对列表进行排序,CSS has an order property 您也许可以利用。

【讨论】:

  • 关于 CSS order 属性的要点。这也是我在搜索时遇到的解决方案之一。但同样的问题是我必须使用.classes 为每个条件定义单独的订单。但也许我会用这个,因为它不会太长。
  • @radiantshaw 虽然通常不受欢迎,但您仍然可以将订单值直接附加为style 属性。所以你可以做&lt;li style="order: 1"&gt;Fourth&lt;/li&gt;,不过这真的取决于你的要求。
  • 我认为这在一定程度上是可以接受的。好点子!
【解决方案4】:

你需要给ulli的元素添加一个唯一的选择器,这样你就可以选择它们,比如我正在考虑一个select会包含条件选择器,然后在@ 987654324@的select我正在调用一个函数,里面正在调用一个函数来改变列表的顺序。

这里是sn-p:

var list = $('#listToOrder');
var original_order = $('#listToOrder').html();
$('#ddlchangeOrder').on('change', function() {
  var selected_value = this.value;
  orderSwitcher(selected_value);
});

function orderSwitcher(order) {
  switch (order) {
    case "foo":
      var elementToPush = list.find('li[data-select="4"]').clone(); //creating a clone of the element
      list.find('li[data-select="4"]').remove(); //removing the existing element
      list.prepend(elementToPush);
      break;
    case "bar":
      var elementToPush = list.find('li[data-select="2"]').clone(); //creating a clone of the element
      list.find('li[data-select="2"]').remove(); //removing the existing element
      list.prepend(elementToPush);
      break;
      //add other cases as per your need.
    default:
      list.html(original_order);
      break;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="listToOrder">
  <li data-select="1">First</li>
  <li data-select="2">Second</li>
  <li data-select="3">Third</li>
  <li data-select="4">Fourth</li>
  <li data-select="5">Fifth</li>
</ul>
<div>
  <label for="ddlchangeOrder">Define Order</label>
  <select name="" id="ddlchangeOrder">
    <option value="0">Select Order</option>
    <option value="foo">Foo</option>
    <option value="bar">Bar</option>
    <option value="no">no Case</option>
  </select>
</div>

【讨论】:

  • 这样的问题是,如果有 100 个状态,那么 switch 的情况会变得很长。而且代码很难维护。即使这样可以完成工作,我也需要更好的解决方案。
【解决方案5】:

var values= ["First", "Second", "Third", "Fourth", "Fifth"];
//Re-arrange values on condition(state == "bar"/"foo" etc)

var element = '<ul>'

for(var i = 0; i < values.length; i++){
    var value = values[i];
    element += '<li>'+ value+ '</li>';
} 

element += '</ul>';
document.getElementById("ulContainer").innerHTML = element;
&lt;div id="ulContainer"&gt;&lt;/div&gt;

【讨论】:

  • 但我仍然需要使用if 条件重新排列值,对吧?
  • 是的。我以为你想要这样 :) 根据条件重新排列。
  • 可接受的答案,但仍在等待更好的解决方案。
猜你喜欢
  • 2021-02-01
  • 1970-01-01
  • 2012-04-07
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
  • 2014-07-24
  • 2022-11-29
  • 1970-01-01
相关资源
最近更新 更多