如何将 NGXS 与路由解析器一起使用?
非常简单 :D store.dispatch 返回一个 observable,它将在所有异步工作完成后生成一个事件并完成,因此您可以轻松地在解析器中调度操作。
假设您有一个名为 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);
})
);
}
}
所以你要做的是创建一个解析器,在那里调度一个动作并将流映射到文章数组,就像这样:
@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) {}
}