SaaS管理系統開發經驗------Dva(Redux)實戰經驗分享
寫在前面
SaaS 2.1 已經開發結束了,時間早已過去了好幾個月,今天若是說從Dva基礎入門講起的話,實在沒必要 ,沒有比官網上的作者自己的介紹更專業更詳盡了,既然這個系列想說的是實戰經驗,那今天就把Dva 在實戰中總結一下,向各位大佬求證一下:
Dva封裝了Redux和Redux-saga,最大限度地精簡了Redux ,所以在記錄實戰經驗的時候是視他們為一體的。
一些細節
1. Dva的modal是需要註冊的。
特別是剛入門Dva的時候,很大可能會遇到由於忘記註冊modal而抓狂到懷疑人生的;
app.model(require('./models/global' ).default);
複製程式碼
2. Modal的拆分---業務層還是資料層。
3. effect中的方法是可以跨Modal中呼叫的,但是要宣告名稱空間。
export default {
namespace: 'user',
state: {
identity: 0,
locale:'zh_CN',
},
effects: {
* handleChangeIdentity({ payload, callback }, { call, put }) {
const response = yield call(getChangeIdentity, payload);
yield put({ type : 'doChangeIdentity', payload: response.data });
// 這裡通過名稱空間account呼叫 account這個Modal的方法
yield put({ type: 'account/doChangeIdentity', payload: response.data });
}
...
}
...
}
複製程式碼
4. 元件中可以直接呼叫reducer中的方法,來更改Modal中的state,從而重新整理頁面。
也意味著同一個Modal內effect中的方法名不要和reducer中的方法名重複。
5. effect中的拿state中的資料---select。
effects: {
* handleChangeIdentity(_, { call, put , select}) {
// 這裡通過select方法拿取state中的資料
const identity=yield select(state=>state.user.identity);
const response = yield call(getChangeIdentity, {identity});
...
}
...
}
複製程式碼
注意這裡的state不是當前Modal的state,而是最頂層的state
6. Modal中方法命名經驗:handle--get/post---do。
由於一個介面請求需要定義三個方法:方法呼叫effect,執行請求service,改變state reducer,所以為了方便追蹤採用effect裡使用handleXXX命名,service使用get/postXXX命名, reducer裡採用doXXX命名。
從此再也不用為方法太多,命名發愁了
關於使用HashHistory還是BrowserHistory
使用 hashHistory,瀏覽器上看到的 url 會是這樣的: /#/user/hai?pk=ads
使用 browserHistory,瀏覽器上看到的 url 會是這樣的:/user/hai
當然看起來 browserHistory 很好很理想,但 browserHistory 需要 server 端支援,就PWA(單頁)應用來講,是不太合適的, 畢竟單頁應用的路由是自己控制的。
而使用hashHistory的時候,因為 url 中 # 符號的存在,從 /#/ 到 /#/user/haishanh 瀏覽器並不會去傳送一次 request, react-router 自己根據 url 去 render 相應的模組。
如果使用 browserHistory 的時候,瀏覽器從 / 到 /user/haishanh 是會向 server 傳送 request 的。 所以 server 端是要做特殊配置的。比如用的 express 的話,你需要 handle 所有的路由 app.get('*', (req, res) => { ... }), 使用了 nginx 的話,nginx也要做相應的配置。
單向資料流之Modal中的state 與元件中的state
安裝Redux單向資料流的設計思想,資料流向為:dispatch開始請求資料----->reducer接收資料更新state----->頁面重新整理,也就是整個專案共同維護一個state樹----store,也就是說元件內部不該有state,這樣更符合Redux單向資料流思想。開發中發現一些頁面臨時資料比如一個彈窗顯示隱藏都需要dispatch一個action,然後reducer裡更新state,要橫跨好幾檔案,開發效率也跟著降低了。所以最後採取了一個折中一點的方法,一些頁面內部狀態之類的臨時資料還是放元件內部State。
除開一些元件臨時狀態使用本地state,其他state都應該屬於全域性。
當然這也引入下一個問題:當元件內部狀態需要根據後臺資料改變時怎麼處理?這就是下一個問題....
關於Dva effect回撥修改本地state
接上回書:當元件內部狀態需要根據後臺資料改變時,可以採用回撥的方式解決。
getNotice = () => {
const { dispatch } = this.props;
dispatch({
type: 'workbench/handleGetNotice',
payload: {
isRead: 0,
},
// 在action傳遞一個callback方法作為回撥
callback: (data) => {
this.setState({
visible:data.isOk
});
},
});
};
handleGetNotice({ payload,callback }, { call, put }) {
const response = yield call(getNotice, a);
// 在收到資料時執行回撥方法
callback&&callback(response.data);
}
複製程式碼
這裡特別注意:不要因為這裡可以執行回撥改變state,而偷懶將state全部放元件裡,如此就違背了Redux單向資料流,如此你又何必煞費苦心使用Redux呢?我想Dva作者不會再官網推薦這種寫法,大概是因為它確實違背了單向資料流的紅線,而我也只是在極其複雜的情況下才用過幾次,應急之用罷了。
今天就想到這麼多了,以後如果想起別的再來補上吧。也請各位行家裡手不吝賜教!