Имея один список элементов, который показан несколько раз, есть ли метод, позволяющий сортировать каждое представление независимо? - PullRequest
0 голосов
/ 06 июля 2018

У меня есть один список \ источник треков, который отображается несколько раз на разных страницах. Я хочу разрешить пользователям сортировать этот список независимо (за страницу).

Я мог бы создать несколько копий этого списка, но проблема в том, что этот список можно изменить (добавить \ удалить \ переименовать дорожки и т. Д.), Поэтому в этом случае несколько копий этого списка, кажется, не является хорошим решением. потому что такие изменения должны применяться ко всем копиям списка.

Существует ли какая-либо методика, позволяющая сортировать дорожки независимо, имея только один источник дорожек?

Демо

1 Ответ

0 голосов
/ 06 июля 2018

У вас есть два основных варианта:

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);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...