Dva.js總結
1.why Dva
dva 是基於現有應用架構 (redux + react-router + redux-saga 等)的一層輕量封裝,沒有引入任何新概念,全部程式碼不到 100 行。dva 實現上儘量不建立新語法,而是用依賴庫本身的語法,比如 router 的定義還是用 react-router 的 JSX 語法的方式(dynamic config 是效能的考慮層面,之後會支援)。
app.model({ namespace: 'products', state: {//State 表示 Model 的狀態資料 list: [], loading: false, }, subscriptions: [ function(dispatch) { dispatch({type: 'products/query'});//觸發 action 的函式,action 是改變 State 的唯一途徑 }, ], effects: {//Effect 被稱為副作用,在我們的應用中,最常見的就是非同步操作 ['products/query']: function*() { yield call(delay(800)); yield put({ type: 'products/query/success', payload: ['ant-tool', 'roof'], }); }, }, //在dva中reducers聚合積累的結果是當前model的state 物件。通過actions中傳入的值, //與當前 reducers 中的值進行運算獲得新的值(也就是新的 state) reducers: { ['products/query'](state) { return { ...state, loading: true, }; }, ['products/query/success'](state, { payload }) { return { ...state, loading: false, list: payload }; }, }, });
2.簡單明瞭的Dva資料流向
資料的改變發生通常是通過使用者互動行為或者瀏覽器行為(如路由跳轉等)觸發的,當此類行為會改變資料的時候可以通過 dispatch 發起一個 action,如果是同步行為會直接通過 Reducers 改變 State ,如果是非同步行為(副作用)會先觸發 Effects 然後流向 Reducers 最終改變 State
3.Dva Router控制
dva 例項提供了 router 方法來控制路由,使用的是react-router
const app = dva(); import { Router, Route } from 'dva/router'; app.router(({history}) => <Router history={history}> <Route path="/" component={HomePage} /> </Router> );
4.dva 應用的最簡結構(帶 model)
// 建立應用 const app = dva(); // 註冊 Model app.model({ namespace: 'count', state: 0, reducers: { add(state) { return state + 1 }, }, effects: { *addAfter1Second(action, { call, put }) { yield call(delay, 1000);//非同步操作 yield put({ type: 'add' });//類似於dispatch發action }, }, }); // 註冊檢視 app.router(() => <ConnectedApp />); // 啟動應用 app.start('#root');
5.AntDesignPro1.0專案中的Dva
1.index.js
const app = dva({ history: createHistory(),//history可以用來跳轉路由內含location屬性,這裡修改history預設介面,其他介面不變----初始化 }); // 2. Plugins app.use(createLoading());//載入外掛這裡應該載入的是載入動畫外掛 // 3. Register global model app.model(require('./models/global').default);//將src/modles裡面的東西灌進去,通過namespace取 // 4. Router app.router(require('./router').default);//全域性掛載路由資訊 // 5. Start app.start('#root'); export default app._store;
2.router.js
export const getRouterData = app => { const routerConfig = { '/': { component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')), }, '/person/personbasetwo': {//新增路徑指向引入的元件,這條資料會被getRoutes函式渲染成真正的<Route>包裹的路由 component: dynamicWrapper(app, ['personbaseTwo'], () => import('../routes/Person/PersonBaseTwo')), }, '/person/baseInfo/:id': {//dynamicWrapper函式會吧[]裡面資料放到app的model屬性裡,app是dva的例項 component: dynamicWrapper(app, ['personbase'], () => import('../routes/Person/PersonBase/BaseInfo')), }, ·······
3.connect連線model
/*dva的例項app中應該匯入了所有的model,好像是在router中匯入的, 這裡用解構賦值從model中取值,為元件匯入props,loading為dva提供的動畫外掛*/ @connect(({ personbaseTwo, loading }) => ({ personbaseTwo, searchLoading: loading.effects['personbaseTwo/getList'], //loding被這個非同步函式影響,非同步操作中就為ture,結束就為false loading: loading.effects['personbaseTwo/listpage'], }))//從model中取資料生成自己想要的物件結構通過@修飾器放到下面元件中去 class personbaseTwo extends Component { constructor(props){ super(props); this.state = { } } componentWillMount(){//元件將要渲染時拿到預設的一頁多少條和當前頁這些資料 const { personbaseTwo:{pagination} }= this.props; const { page,pageSize } = pagination; this.props.dispatch({//轉到namespace為personbaseTwo下面的listpage方法拿到頁碼為page的資料 type:'personbaseTwo/listpage',//介面根據page只去此頁資料 payload:{ page, pageSize, }, }); } ·······
4.跳轉路由
onOk() {//點選確定執行的函式 const {id}= record; than.props.dispatch(routerRedux.push({//用來跳轉路由的 pathname: `/person/baseInfoTwo/${id}`,//用這個pathname重新渲染路由頁面並傳ID })) },