angular - 如何使用 ngrx/component-store 示例在初始化时不发出事件?

标签 angular ngrx ngrx-store

我正在创建一个与 MatPaginator 类似的组件,但使用 ComponentStore遵循此docs它似乎工作得很好,除了 @Output page 在初始化时发出的事实是意外的。预期的行为是仅在用户更改页面时发出,就像在 Material 版本中一样。

这是重要的代码(它与链接的文档相同):

PaginatorStore:

@Injectable()
export class PaginatorStore extends ComponentStore<PaginatorState> {
  private readonly pageIndexChanges$ = this.state$.pipe(
    map(({ pageIndex }) => pageIndex),
    pairwise()
  );
 
  readonly page$: Observable<PageEvent> = this.select(
    this.pageIndexChanges$,
    this.select((state) => [state.pageSize, state.length]),
    ([previousPageIndex, pageIndex], [pageSize, length]) => ({
      pageIndex,
      previousPageIndex,
      pageSize,
      length,
    }),
    { debounce: true }
  );
}

PaginatorComponent:

@Component({ providers: [PaginatorStore] })
class Component {
  @Output() readonly page = this.paginatorStore.page$;
}

请注意,我还打开了 issue在存储库中,但直到现在我才得到任何答案。

ComponentStore DEMO

Material DEMO

最佳答案

ngrx 存储的行为类似于 BehaviorSubject这意味着在订阅时您将始终获得当前状态。一开始,这是您创建商店时设置的初始状态。

如果您想从下一个更改开始,您可以添加 skip运算符并跳过第一个值,这样您将永远不会获得当前状态,而只能接收之后的事件。

@Component({ providers: [PaginatorStore] })
class Component {
  @Output() readonly page = this.paginatorStore.page$.pipe(skip(1));
}

对于你的情况,我认为你应该采用更复杂的解决方案,因为 Angular 期望 @Output 属性使用 EventEmitter类型。事件发射器也是 Subject因此您可以直接订阅商店 Observable,并且值将自动传播。

以下是此场景的示例实现。

@Component({ providers: [PaginatorStore] })
class Component implements OnDestroy {
  @Output() readonly page = new EventEmitter<PageEvent>();

  private destroyed = false;

  constructor(private readonly paginatorStore: PaginatorStore) {
    this.paginatorStore.page$.pipe(skip(1), takeWhile(() => !this.destroyed)).subscribe(this.page);
  }

  ngOnDestroy(): void {
    this.destroyed = true;
  }
}

你可以看到我还添加了一个 OnDestroy实现以防止组件被销毁后保留订阅,因为这可能导致内存泄漏。

这里还有一个指向 fork of your StackBlitz 的链接这样您就可以看到它的实际效果。

关于angular - 如何使用 ngrx/component-store 示例在初始化时不发出事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66233833/

相关文章:

angular - Jasmine-core 避免安装 angular-devkit/build-angular

angular - 输入焦点时如何隐藏错误消息?

angular - 是否有可能在 ngrx-effects 内部抛出错误而不完成 Observable 流?

angular - ngrx/store 状态未在调用的 reducer 函数中更新

angular - 如何使用 indexedDB 的 promise 在@ngrx/core 中设置initialState

angular - 是否有任何官方文档指定 ~ (代字号)解析为 node_modules/in Angular scss 导入路径?

angular - Ionic 3 值绑定(bind)地理定位

Angular Material 和 NGRX : mat-expansion-panels close when Input changes

angular - @ngrx/effect 中止 Angular 应用程序中的多个 REST 调用

angular - ngrx 突出显示网格中新添加的项目