2017-06-12 52 views
1

我想弄清楚如何將許多資源狀態合併到各種組件狀態以及構成AppState的是什麼。這裏的大多數ngrx指南/例子只能處理一個資源(例如一本書)或一個有限的狀態(例如書和一本選定的書),但我認爲我沒有遇到過比這更復雜的任何事情。如何使用Reducers爲多個資源/組件構建一個AppState?

當你有十幾種資源時,你需要做什麼?在不同的狀態下(列表,項目,搜索項,菜單項,過濾器等)在多個組件中需要不同的資源狀態?

我已搜索周圍,我想出了下面的結構,但我不相信這是想要的結果:

AppState & reducer 
<- combine reducers 
- Component states & reducers 
<- combine reducers 
-- Resource states & reducers 

您將結合資源減速(例如bookReducer,booksReducer,bookSearchTitleReducer)轉換爲與組件相關的reducer(例如bookSearchReducer),然後將所有組件縮減器與一個AppState組合成一個reducer,並在AppModule中使用它。

這是要走的路嗎還是有另一種(適當)的方式來做到這一點?如果這是一個很好的方法,我會在Store構造函數中使用Store還是Store?

[編輯]

確定,NGRX-示例應用內並處理多種組分,我看到的只是在組件級別未在資源級別創建狀態,結合了狀態和相應各減速器和使用組件構造函數中的完整狀態對象:'store:Store'。

我想,因爲這是一個官方的例子,這將是處理狀態/ reducer的預期方式。

回答

2

[編輯]

v4 ngrx是更易於使用,具有更好的文檔和示例應用程序來幫助你。以下內容主要與v2相關,它的怪癖在v4中不再是問題。

[作廢]

大量的試驗和錯誤之後,我發現了一個很好的,工作公式。我要在這裏分享它的主旨,也許它會幫助別人。

減速機構成指南幫了我很大的忙,並說服我去參加我的原始狀態/減速機結構的資源>組件>應用程序。該指南太大而不適合在這裏,您可能需要最新版本here

這裏有一個快速運行的是我曾在一些關鍵文件做兩個部件的應用,有兩個基本的資源(用戶和資產)與衍生物(列表)和參數(搜索)了。

store/reducers/user/index.ts:

import { ActionReducer, combineReducers } from '@ngrx/store'; 

import { authenticatedUserReducer } from './authenticatedUser.reducer'; 
import { selectedUserReducer } from './selectedUser.reducer'; 
import { userListReducer } from './userList.reducer'; 
import { userSearchReducer } from './userSearch.reducer'; 
import { User } from '../../models'; 

const reducers = { 
    authenticated: authenticatedUserReducer, 
    selected: selectedUserReducer, 
    list: userListReducer, 
    search: userSearchReducer 
}; 

interface UserState { 
    authenticated: User, 
    selected: User, 
    list: User[], 
    search: string 
} 

const reducer: ActionReducer<UserState> = combineReducers(reducers); 

function userReducer(state: any, action: any) { 
    return reducer(state, action); 
} 

export { userReducer, UserState }; 

store/reducers/asset/index.ts:

import { ActionReducer, combineReducers } from '@ngrx/store'; 

import { selectedAssetReducer } from './selectedAsset.reducer'; 
import { assetListReducer } from './assetList.reducer'; 
import { assetSearchReducer } from './assetSearch.reducer'; 
import { Asset } from '../../models'; 

const reducers = { 
    selected: selectedAssetReducer, 
    list: assetListReducer, 
    search: assetSearchReducer 
}; 

interface AssetState { 
    selected: Asset, 
    list: Asset[], 
    search: string 
} 

const reducer: ActionReducer<AssetState> = combineReducers(reducers); 

function assetReducer(state: any, action: any) { 
    return reducer(state, action); 
} 

export { assetReducer, AssetState }; 

store/reducers/index.ts:

import { routerReducer, RouterState } from '@ngrx/router-store'; 

import { userReducer, UserState } from './user'; 
import { assetReducer, AssetState } from './asset'; 

const reducers = { 
    router: routerReducer, 
    user: userReducer, 
    asset: assetReducer 
}; 

interface AppState { 
    router: RouterState, 
    user: UserState, 
    asset: AssetState 
} 

export { reducers, AppState }; 

注:I包含單獨提供,以及路由器減速器。

app.module.ts:

import { BrowserModule } from '@angular/platform-browser'; 
import { NgModule } from '@angular/core'; 
import { FormsModule } from '@angular/forms'; 
import { HttpModule } from '@angular/http'; 
import { RouterModule } from '@angular/router'; 

import { StoreModule } from '@ngrx/store'; 
import { RouterStoreModule } from '@ngrx/router-store'; 

import { reducers } from './store'; 
import { AppComponent } from './app.component'; 
import { AppRoutes } from './app.routes'; 
import { HomeComponent } from './components/home/home.component'; 

@NgModule({ 
    declarations: [ 
    AppComponent, 
    HomeComponent 
    ], 
    imports: [ 
    BrowserModule, 
    FormsModule, 
    HttpModule, 
    RouterModule.forRoot(AppRoutes), 
    StoreModule.provideStore(reducers), 
    RouterStoreModule.connectRouter() 
    ], 
    providers: [], 
    bootstrap: [AppComponent] 
}) 
export class AppModule { } 

注意:使用你所需要的在這裏,廢你做什麼不是。我在/ store中創建了另一個index.ts文件,它將出口減速器,所有模型以及將來的其他一些內容。

home.component.ts:

import { Component } from '@angular/core'; 

import { Observable } from 'rxjs/Observable'; 
import { Store } from '@ngrx/store'; 

import { AppState, User } from '../../store'; 

@Component({ 
    selector: 'home', 
    templateUrl: './home.template.html' 
}) 
export class HomeComponent { 
    user: Observable<User>; 

    constructor (private store: Store<AppState>) { 
    this.user = store.select('user', 'selected'); 
    store.dispatch({ type: 'SET_USER_NAME', payload: 'John' }); 
    store.dispatch({ type: 'ADD_USER_ROLE', payload: 'admin' }); 
    store.dispatch({ type: 'ADD_USER_ROLE', payload: 'wordsmith' }); 
    } 
} 

注意:您可以在您的模板類似{{(user | async)?.name}}測試。

就是這樣。可能有更好的方法來做到這一點,我知道我可以用一個級別來完成它(例如只是基本的資源),這完全取決於你認爲最適合你的應用的東西。

+0

嗨,你有什麼想法,這將在不同的模塊工作,例如我有2個模塊和每個模塊處理某些狀態。我正在努力爲此找到一個體面的解決方案。 –

+0

我已經升級到了ngrx v4,它使用起來更加簡單,並且有特殊的輔助函數來處理子模塊縮減器(例如StoreModule.forFeature('books',redurs)),您必須自己擴展的狀態和在構造函數中存儲使用擴展類型。您可以在[monorepo頁面](https://github.com/ngrx/platform)中找到更多內容,其中包含一個示例應用程序(在那裏查看兒童模塊以獲取靈感) - 它對我有很大幫助。 – Kesarion

相關問題