我一直在查看ngrx 示例应用程序并尝试使用以下内容对其进行扩展:
- 搜索书籍时,查询将作为查询参数写入 url,例如http://localhost:4200/book/find?query=book_title
- 使用包含查询参数的 url 打开页面时,应填充搜索输入框并显示搜索
做这样的事情的正确方法是什么?
我已经添加了我的解决方案,它可以完成工作,但我不确定它是否有任何好处。在其中我将查询参数存储在两个看起来像反模式的地方
我的解决方案:
在 app/books/effects/books.ts 中在搜索效果中添加了一个路由导航,这样每当触发搜索时,都会使用查询字符串更新 url
search$: Observable<Action> = this.actions$.pipe(
ofType<Search>(BookActionTypes.Search),
debounceTime(this.debounce || 300, this.scheduler || async),
map(action => action.payload),
switchMap(query => {
if (query === '') {
return empty();
}
const nextSearch$ = this.actions$.pipe(
ofType(BookActionTypes.Search),
skip(1)
);
return this.googleBooks.searchBooks(query).pipe(
takeUntil(nextSearch$),
map((books: Book[]) => {
// added //
this.router.navigate([], {
queryParams: { query: query },
queryParamsHandling: 'merge',
});
///////////
return new SearchComplete(books);
}),
catchError(err => of(new SearchError(err)))
);
})
);
在 app/reducers/index.ts 中添加了路由器查询参数的选择器:
export const getRouterState = createFeatureSelector<
fromRouter.RouterReducerState<RouterStateUrl>
>('router');
export const getQueryParams = createSelector(
getRouterState,
state => state.state.queryParams
);
在 app/books/containers/find-book-page.ts 添加了方法
urlQuery() {
// dispatch a search action if there is a query string in url
this.store
.pipe(select(fromRoot.getQueryParams), take(1))
.subscribe(queryParams => {
if (queryParams.query) {
this.search(queryParams.query);
}
});
}
这个方法是从 find-book-page 组件中的构造函数调用的,所以当这个组件被加载时,它会检查 url 中是否有查询字符串,如果有,则使用该查询字符串调度一个操作
constructor(private store: Store<fromBooks.State>) {
this.searchQuery$ = store.pipe(select(fromBooks.getSearchQuery), take(1));
this.books$ = store.pipe(select(fromBooks.getSearchResults));
this.loading$ = store.pipe(select(fromBooks.getSearchLoading));
this.error$ = store.pipe(select(fromBooks.getSearchError));
this.urlQuery();
}