只有一次显示几次的项目清单,是否有任何技术可以让每个表示形式独立排序?

时间:2018-07-06 11:57:40

标签: javascript arrays sorting

我有一个曲目列表\来源,在不同页面上显示了几次。我想允许用户对列表进行独立排序(每页)。

我可以创建此列表的几个副本,但是问题是可以更改此列表(添加\删除\重命名曲目等),因此在这种情况下,此列表的几个副本似乎不是一个好的解决方案,因为此类更改必须应用于列表的所有副本。

有没有一种技术可以仅对一个轨道源进行独立的轨道排序?

Demo

1 个答案:

答案 0 :(得分:0)

您基本上有两种选择:

1)当列表更改时,通知所有拥有其列表排序版本的所有组件,以便它们可以复制更改的列表并对其进行排序/显示。为此,您需要一种发出事件的方式,例如作为混合类:

const EventEmitter = Parent => class EventEmitter extends Parent {
  constructor(...args) {
     super(...args);
     this._emitters = {};
  }

  trigger(evt, ...args) {
    (this._emitters[evt] || []).forEach(emitter => emitter(...args));
  }

  on(evt, handler) {
    (this._emitters[evt] || (this._emitters[evt] = [])).push(handler);
  }
};

然后,您可以代理一个数组,以便在每次更改时触发更新事件:

 const ChangeEmitter = Parent => {
    const Mixin = EventEmitter(Parent);
    return (...args) => new Proxy(
       new Mixin(...args),
       {
          set(obj, prop, value) {
             const result = Reflect.set(...arguments);
             obj.trigger("update", obj);
             return result;
          }
       }
    );
 };

这看起来很复杂,但是现在我们可以这样做:

 // Our source of truth:
 const base = new ChangeEmitter(Array);

  // One of the functions that renders the data:
 function renderSorted(array) {
   const sorted = array.sort();
   document.body.innerHTML = sorted;
 }
 renderSorted(base); // Initial render
 base.on("update", renderSorted);

 base[0] = 1;

因此,每当我们更新基本数组时,所有渲染器都将再次被调用,并且所有内容都可以更新。


2)创建一些排序的数组,并将每个突变应用于所有数组。为此,我们需要一个排序数组:

class SortedArray extends Array {
  constructor(sorter, ...args) {
    super(...args);
    this.sorter = sorter;
    this.sort(sorter);
  }

  // Do insertion sort
  add(el) {
    let index = 0;
    while(index <= this.length && this.sorter(el, this[index]) > 0) index++;
    this splice(index, 0, el);
  }

  remove(el) {
     this.splice(this.indexOf(el), 1);
  }
}

以及一种并行更改多个数组的方法:

 const unifyArrays = (...arrays) => ({
   add(el) {  arrays.forEach(arr => arr.add(el)); },
   remove(el) { arrays.forEach(arr => arr.remove(el)); }
 });

现在您可以这样做:

const sorted = new SortedArray((a, b) => a - b);
const reversed = new SortedArray((a, b) => b - a);

const base = unifyArrays(sorted, reversed);

base.add(1);

请确保您可以结合使用这两种方法,以便在更改数组时会发出偶数。