angular – 相同NgRx功能模块的独立实例
我正在使用NgRx 5开发一个Angular 5项目.到目前为止,我已经实现了一个骨架应用程序和一个名为“Search”的功能模块,它以封装的方式处理自己的状态,动作和缩减器(通过使用forFeature语法).
该模块有一个根组件(搜索容器),它呈现整个子组件树 – 它们组成了搜索UI和功能,它具有复杂的状态模型和大量的操作和缩减器. 有强烈的要求说: >功能模块应相互隔离导入, 所以我的问题是: 我怎样才能有多个< search-container>< / search-container>一起确保它们独立运作?例如,我想在窗口小部件的一个实例中调度搜索操作,而不是在所有窗口小部件中看到相同的搜索结果. 任何建议都非常感谢.谢谢!
我遇到了类似的问题,想出了以下解决方法.
重申您的要求只是为了确保我正确理解它们: >您有一个模块“搜索”具有自己的组件/状态/减速器/操作等. 解决方案:利用行动的元数据 通过操作,存在元数据的概念.基本上,除了payload-Property之外,您还在操作对象的顶层有一个元属性.这与“具有相同的动作,但在不同的环境中”的概念很好地配合.然后,元数据属性将为“id”(如果需要,还有更多内容)来区分要素实例.在根状态中有一个reducer,定义所有动作一次,元数据帮助reducer / effects知道调用哪个“子状态”. 州看起来像这样: export interface SearchStates { [searchStateId: string]: SearchState; } export interface SearchState { results: string; } 动作如下所示: export interface SearchMetadata { id: string; } export const search = (params: string,meta: SearchMetadata) => ({ type: 'SEARCH',payload: params,meta }); reducer像这样处理它: export const searchReducer = (state: SearchStates = {},action: any) => { switch (action.type) { case 'SEARCH': const id = action.meta.id; state = createStateIfDoesntExist(state,id); return { ...state,[id]: { ...state[id],results: action.payload } }; } return state; }; 您的模块为root提供一次reducer和可能的效果,对于每个功能(也称为搜索),您提供带有元数据的配置: // provide this inside your root module @NgModule({ imports: [StoreModule.forFeature('searches',searchReducer)] }) export class SearchModuleForRoot {} // use forFeature to provide this to your search modules @NgModule({ // ... declarations: [SearchContainerComponent] }) export class SearchModule { static forFeature(config: SearchMetadata): ModuleWithProviders { return { ngModule: SearchModule,providers: [{ provide: SEARCH_METADATA,useValue: config }] }; } } @Component({ // ... }) export class SearchContainerComponent { constructor(@Inject(SEARCH_METADATA) private meta: SearchMetadata,private store: Store<any>) {} search(params: string) { this.store.dispatch(search(params,this.meta); } } 如果要隐藏组件中的元数据复杂性,可以将该逻辑移动到服务中,并在组件中使用该服务.在那里,您还可以定义选择器.将服务添加到forFeature中的提供者. @Injectable() export class SearchService { private selectSearchState = (state: RootState) => state.searches[this.meta.id] || initialState; private selectSearchResults = createSelector( this.selectSearchState,selectResults ); constructor( @Inject(SEARCH_METADATA) private meta: SearchMetadata,private store: Store<RootState> ) {} getResults$() { return this.store.select(this.selectSearchResults); } search(params: string) { this.store.dispatch(search(params,this.meta)); } } 在搜索选项卡模块中使用: @NgModule({ imports: [CommonModule,SearchModule.forFeature({ id: 'searchTab1' })],declarations: [] }) export class SearchTab1Module {} // Now use <search-container></search-container> (once) where you need it 如果您的搜索选项卡看起来完全相同且没有自定义,您甚至可以更改SearchModule以将searchContainer作为路径提供: export const routes: Route[] = [{path: "",component: SearchContainerComponent}]; @NgModule({ imports: [ RouterModule.forChild(routes) ] // rest stays the same }) export class SearchModule { // ... } // and wire the tab to the root routes: export const rootRoutes: Route[] = [ // ... {path: "searchTab1",loadChildren: "./path/to/searchtab1.module#SearchTab1Module"} ] 然后,当您导航到searchTab1时,将呈现SearchContainerComponent. …但我想在单个模块中使用多个SearchContainerComponents 您可以在组件级别应用相同的模式: 在SearchService启动时随机创建元数据ID. @Injectable() export class SearchService implements OnDestroy { private meta: SearchMetadata = {id: "search-" + Math.random()} // .... } @Component({ // ... providers: [SearchService] }) export class SearchContainerComponent implements OnInit { // ... } 如果您希望ID是确定性的,则必须在某处对它们进行硬编码,然后将它们作为输入传递给SearchContainerComponent,然后使用元数据初始化服务.这当然会使代码更复杂一些. 工作实例 每个模块: 每个组件: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |