繁体   English   中英

如何将NGXS与路由解析器一起使用?

[英]How to use NGXS with route resolvers?

假设我有一个管理文章的CRUD应用程序。 将NGXS与路线参数结合使用的正确方法是什么?

打开应用程序时,我位于/ 单击按钮会将我带到/articles

  • 现在会发生什么? 我是否需要一个路由解析器来分派NGXS操作来加载商品,或者是负责该商品的商品的容器组件?
  • 当文章列表已加载(通过解析程序或容器本身)时,我想单击特定的文章,例如,将我带到/articles/1 再说一遍:我这里需要路由解析器吗?

如果我需要路由解析器:如何在加载状态时显示特定组件中的加载微调器(例如,在商品列表中显示微调器)? 唯一可行的解​​决方案是从解析器返回Observable<Observable>

如果不是:如果我直接前往/articles/1 ,谁将调度必要的操作使我的状态正确(在这种情况下,文章本身尚未加载,那么应该如何加载特定文章)?

我找不到有关此主题的任何资源。 我发现的所有示例应用程序都不介意当前的路由,这会导致非常糟糕的UX imo。

如何将NGXS与路由解析器一起使用?

非常简单:D store.dispatch返回一个可观察的对象,它将在所有异步工作完成后生成一个事件并完成,因此您可以轻松地在解析器中分派动作。

假设您有一个名为GetArticles的操作:

export class GetArticles {
  public static readonly type = '[Articles] Get articles';
}

您可能希望有一个状态来存储所有文章,还需要一个响应GetArticles的操作处理程序:

@State({
  name: 'articles',
  defaults: []
})
export class ArticlesState {
  constructor(private articlesService: ArticlesService) {}

  @Action(GetArticles)
  public getArticles(ctx: StateContext<Article[]>) {
    return this.articlesService.getArticles().pipe(
      tap(articles => {
        ctx.setState(articles);
      })
    );
  }
}

因此,您要做的是创建一个解析器,在其中分配一个操作并将流映射到articles数组,如下所示:

@Injectable()
export class ArticlesResolver implements Resolve<Article[]> {
  constructor(private store: Store) {}

  public resolve() {
    return this.store.dispatch(new GetArticles()).pipe(
      map(() => this.store.selectSnapshot(ArticlesState))
    );
  }
}

就这样,您的ArticlesComponent已经可以通过ActivatedRoute.prototype.snapshot.data.articles访问预加载的文章(假设您已将resolver与诸如resolve: { articles: ArticlesResolver }组件链接resolve: { articles: ArticlesResolver } )。


考虑到有关路由到/articles/1类的特定文章的问题,如果您已经预先加载了文章-您是否不能直接从articles数组中获得必要的文章? 您可以创建一个选择器,该选择器将通过id搜索文章:

export class ArticlesState {
  public static getArticleById(id: string) {
    return createSelector(
      [ArticlesState],
      (articles: Article[]) => articles.find(article => article.id === id)
    );
  }
}

因此,您在ArticleComponent要做的就是通过使用id调用此选择器工厂从商店中选择快照:

export class ArticleComponent {
  public article: Article = this.store.selectSnapshot(
    ArticlesState.getArticleById(this.route.snapshot.params.id)
  );

  constructor(private route: ActivatedRoute, private store: Store) {}
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM