如何将 NGXS 与路由解析器一起使用?
How to use NGXS with route resolvers?
假设我有一个管理文章的 CRUD 应用程序。结合使用 NGXS 和路由参数 的正确方法是什么?
当我打开应用程序时,我在 /
。单击按钮会将我带到 /articles
:
- 现在发生了什么?我是否需要一个路由解析器来分派 NGXS 操作来加载文章,或者文章的容器组件是否负责?
- 当文章列表已加载(通过解析器或容器本身)时,我想单击将我带到
/articles/1
的特定文章。再一次:我需要一个路由解析器吗?
如果我需要路由解析器:如何在加载状态时在特定组件中显示加载微调器(例如在文章列表中显示微调器)?唯一可能的解决方案是从解析器返回 Observable<Observable>
。
如果否:如果我直接前往 /articles/1
谁会派遣必要的操作来使我的状态正确(在这种情况下,文章本身尚未加载,那么应该如何加载一篇特定的文章)?
我找不到关于此主题的任何资源。我发现的所有示例应用程序都不介意当前的路线,这会导致非常糟糕的用户体验 imo。
How to use NGXS with route resolvers?
非常简单 :D store.dispatch
returns 一个可观察对象,它将生成一个事件并在所有异步工作完成后完成,因此您可以轻松地在解析器中调度操作。
假设您有一个名为 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
数组中获取必要的文章吗?您可以创建一个 selector 来搜索 id
:
的文章
export class ArticlesState {
public static getArticleById(id: string) {
return createSelector(
[ArticlesState],
(articles: Article[]) => articles.find(article => article.id === id)
);
}
}
因此,您在 ArticleComponent
中所要做的只是 select 通过使用 id
调用此 select 或工厂从商店获取快照:
export class ArticleComponent {
public article: Article = this.store.selectSnapshot(
ArticlesState.getArticleById(this.route.snapshot.params.id)
);
constructor(private route: ActivatedRoute, private store: Store) {}
}
假设我有一个管理文章的 CRUD 应用程序。结合使用 NGXS 和路由参数 的正确方法是什么?
当我打开应用程序时,我在 /
。单击按钮会将我带到 /articles
:
- 现在发生了什么?我是否需要一个路由解析器来分派 NGXS 操作来加载文章,或者文章的容器组件是否负责?
- 当文章列表已加载(通过解析器或容器本身)时,我想单击将我带到
/articles/1
的特定文章。再一次:我需要一个路由解析器吗?
如果我需要路由解析器:如何在加载状态时在特定组件中显示加载微调器(例如在文章列表中显示微调器)?唯一可能的解决方案是从解析器返回 Observable<Observable>
。
如果否:如果我直接前往 /articles/1
谁会派遣必要的操作来使我的状态正确(在这种情况下,文章本身尚未加载,那么应该如何加载一篇特定的文章)?
我找不到关于此主题的任何资源。我发现的所有示例应用程序都不介意当前的路线,这会导致非常糟糕的用户体验 imo。
How to use NGXS with route resolvers?
非常简单 :D store.dispatch
returns 一个可观察对象,它将生成一个事件并在所有异步工作完成后完成,因此您可以轻松地在解析器中调度操作。
假设您有一个名为 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
数组中获取必要的文章吗?您可以创建一个 selector 来搜索 id
:
export class ArticlesState {
public static getArticleById(id: string) {
return createSelector(
[ArticlesState],
(articles: Article[]) => articles.find(article => article.id === id)
);
}
}
因此,您在 ArticleComponent
中所要做的只是 select 通过使用 id
调用此 select 或工厂从商店获取快照:
export class ArticleComponent {
public article: Article = this.store.selectSnapshot(
ArticlesState.getArticleById(this.route.snapshot.params.id)
);
constructor(private route: ActivatedRoute, private store: Store) {}
}