假设我有一个管理文章的CRUD应用程序。将NGXS 与路线参数结合使用的正确方法是什么?
打开应用程序时,我位于/
。单击按钮会将我带到/articles
:
/articles/1
。再说一遍:我这里需要路由解析器吗?如果我需要路由解析器:如何在加载状态时显示特定组件中的加载微调框(例如,在商品列表中显示微调框)?唯一可行的解决方案是从解析器返回Observable<Observable>
。
如果否:如果我直接前往/articles/1
,谁将调度必要的操作以使我的状态正确(在这种情况下,文章本身尚未加载,那么应该如何加载一篇特定的文章)?
我找不到有关此主题的任何资源。我发现的所有示例应用程序都不在乎当前的路由,这会导致非常糟糕的UX imo。
答案 0 :(得分:2)
如何将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
访问预加载的文章(假设您已将解析器链接到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) {}
}