DevGang
Авторизоваться

Akita

Строгий менеджер состояний для приложений на javascript

Грязная проверка

DirtyCheckPlugin полезен в случаях, когда вы хотите указать, является ли состояние грязным (данные в хранилище были изменены). Например, вы можете захотеть отображать кнопку сохранения, только если пользователь что-то меняет.

Чтобы активировать плагин, вам нужно создать новый экземпляр DirtyCheckPlugin, предоставив ему Query:

import { DirtyCheckPlugin } from '@datorama/akita';

export class WidgetsComponent {
  dirtyCheck: DirtyCheckPlugin;

  constructor(private widgetsQuery: WidgetsQuery) {}

  ngOnInit() {
    this.widgets$ = this.widgetsQuery.selectAll();
    this.dirtyCheck = new DirtyCheckPlugin(this.widgetsQuery).setHead();
  }

  updateWidget(id: ID, name: string) {
    this.widgetService.updateWidget(id, name);
  }

  reset() {
    this.dirtyCheck.reset();
  }

  ngOnDestroy() {
    this.dirtyCheck.destroy();
  }
}

С момента вызова setHead() DirtyCheckPlugin берет текущий снимок хранилища и сохраняет его как заголовок (значение, с которым мы сравниваем). При каждом изменении хранилища плагин будет сравнивать его со значением заголовка и уведомлять вас, не является ли состояние грязным.

<button
    [class.disabled]="!(dirtyCheck.isDirty$| async)"
    (click)="reset()">
  Reset Changes
</button>

Вызвав reset(), вы говорите плагину обновить хранилище со значением head.

Плагин также предоставляет специальный метод isPathDirty(), который проверяет, является ли данный путь грязным. Например:

this.dirtyCheck = new DirtyCheckPlugin(this.widgetsQuery).setHead();
this.dirtyCheck.isPathDirty('check.this.path');

Опции плагина

Компаратор по умолчанию сравнивает объект с помощью собственного метода JSON.stringify(), но вы можете передать собственный компаратор, например:

import { isEqual } from 'lodash.isequal';

this.dirtyCheck = new DirtyCheckPlugin(this.widgetsQuery, { comparator: (a, b) => !isEqual(a, b) });

Плагин для грязной проверки может отслеживать определенные свойства в состоянии вашего хранилища, а не только весе хранилище, этого можно достичь, передав ключи свойств в DirtyCheckPlugin, например:

// Отслеживает весе хранилище
new DirtyCheckPlugin(this.widgetsQuery);
// Отслеживает состояние названия хранилища
new DirtyCheckPlugin(this.widgetsQuery, {watchProperty: 'name'});
// Отслеживает набор свойств
new DirtyCheckPlugin(this.widgetsQuery, {watchProperty: ['name', 'color',...]});
// В случае EntityStore мы также можем отслеживать все объекты
new DirtyCheckPlugin(this.widgetsQuery, {watchProperty: 'entities'});

После первого вызова setHead() каждый последующий вызов этого метода будет переустанавливать текущее значение хранилища в качестве заголовка и обновлять грязность на false.

EntityDirtyCheckPlugin

В дополнение к общим функциям грязной проверки, Akita также предоставляет мощный API, помогающий отслеживать один или несколько объектов, а не весе хранилище.

Хороший пример - это когда у вас есть таблица или список сущностей, которые пользователи могут изменять, и вы хотите дать им способ вернуть их для каждой сущности. Вот как вы можете это сделать:

export class WidgetsComponent {
  collection: EntityDirtyCheckPlugin<Widget>;

  constructor(private widgetsQuery: WidgetsQuery) {}

  ngOnInit() {
    this.widgets$ = this.widgetsQuery.selectAll();
    /** Все объекты также будут отслеживать новые объекты, добавленные в хранилище. */
    this.collection = new EntityDirtyCheckPlugin(this.widgetsQuery);
    /** отслеживать конкретные сущности путем передачи entityIds в параметрах: */
    // this.collection = new EntityDirtyCheckPlugin(this.widgetsQuery, { entityIds : 1 });
    // this.collection = new EntityDirtyCheckPlugin(this.widgetsQuery, { entityIds: [ 1,2 ]);
    this.collection.setHead();
  }

  updateWidget(id: ID, name: string) {
    this.widgetService.updateWidget(id, name);
  }

  reset(ids: ID | ID[]) {
    this.collection.reset(ids);
    // this.collection.reset();
  }

  ngOnDestroy() {
    this.collection.destroy();
  }
}

С помощью этой настройки вы можете отслеживать чистоту объекта:

<tbody>
  <tr *ngFor="let widget of widgets$ | async">
    <td>
      <input [value]="widget.name" #name>
    </td>
    <td>
      <button (click)="updateWidget(widget.id, name.value)">save</button>
    </td>
    <td>
      <button
      (click)="revert(widget.id)"
      [class.disabled]="!(collection.isDirty(widget.id) | async)">
        Revert
      </button>
    </td>
  </tr>
</tbody>

Метод isDirty() поддерживает как наблюдаемое, так и необработанное значение:

const asObservable = true/false;
return isDirty(id: ID, asObservable);

Иногда бывает полезно частично сбросить значение сущности при нажатии на возврат. Метод revert() может принимать пользовательскую функцию обновления, которая принимает в качестве параметров текущий заголовок и текущее значение объекта и возвращает измененный объект. Например:

const updateFn = (head, current) => {
  return {
    ...head,
    title: current.title
  };
};
collection.reset(1, { updateFn });

В приведенном выше примере мы возвращаем всю сущность за исключением заголовка (обратите внимание, что это все равно пометит сущность как грязную).

Иногда также полезно проверить, является ли хотя бы один из объектов грязным. Для этого вы можете использовать метод someDirty().

Комментарии
Чтобы оставить комментарий, необходимо авторизоваться