原文:https://www.yuque.com/yuxuanbeishui/zog1rm/tgmgws
今天我們就來聊聊 dva 中的 effects 與 reducers以及其中涉及的關鍵字的使用。如果它們之間工作流程還不太熟悉,請閱讀:分析models源碼
爲了讓小夥伴們更好的理解與使用 effects 與 reducers,我們依然找現有的 models 爲例:
位置:"/src/pages/Profile/models/profile.js"
<div class="lake-codeblock-content"><div class="CodeMirror"><pre class="cm-s-default"><span class="lake-preview-line"><span class="lake-preview-line-number lake-lm-pad-level-1"></span><span class="lake-preview-codeblock-content"><span class="cm-keyword">import</span> { <span class="cm-def">queryBasicProfile</span>, <span class="cm-def">queryAdvancedProfile</span> } <span class="cm-keyword">from</span> <span class="cm-string">'@/services/api'</span>;
export default {
namespace: ‘profile’,
state: {
basicGoods: [],
advancedOperation1: [],
advancedOperation2: [],
advancedOperation3: [],
},
effects: {
fetchBasic({ payload }, { call, put }) {
const response = yield call(queryBasicProfile, payload);
yield put({
type: ‘show’,
payload: response,
});
},
fetchAdvanced(_, { call, put }) {
const response = yield call(queryAdvancedProfile);
yield put({
type: ‘show’,
payload: response,
});
},
},
reducers: {
show(state, { payload }) {
return {
state,
payload,
};
},
},
};
一、effects 內函數有什麼特點?
1、分析 effects 函數形參
從外觀上看,我們發現每個自定義函數前都有 " * " 修飾 ,函數有兩個參數。
有小夥伴反映說,對( { payload } , { call, put })函數參數不太理解,這是固定寫法嗎?裏面還有其他關鍵字嗎?
那好,我們就一起在控制檯上打印出這兩個參數:(action,effects)
我先將上述的 fetchBasic 函數代碼修改如下:
<div class="lake-codeblock-content"><div class="CodeMirror"><pre class="cm-s-default"><span class="lake-preview-line"><span class="lake-preview-line-number lake-lm-pad-level-1"></span><span class="lake-preview-codeblock-content"><span class="cm-meta">...</span>
*fetchBasic( action, effects ) {
console.log( ‘action’, action );
console.log( ‘paramsTwo’, effects );
const { payload } = action;
const { call, put } = effects;
const response = yield call( queryBasicProfile, payload );
yield put( {
type: ‘show’,
payload: response,
} );
},
如果有不懂此寫法的小夥伴: const { payload } = action ,請閱讀:解析賦值
在控制檯上我可以觀察到:
第一個參數 action:
<span data-role="maximize" class="lake-image-editor-maximize" style="display: none;"><span class="lake-icon lake-icon-full-screen"></span></span>
</span>
</span>
</span>
這裏我們可以拿到兩個常用的關鍵字值:payload , type
既然第一個參數 action ,它也叫形參。那在哪個位置調用 fetchBasic 函數的呢?
這個時候我們就要去找 相對應的UI視圖文件了,如下:
<span data-role="maximize" class="lake-image-editor-maximize" style="display: none;"><span class="lake-icon lake-icon-full-screen"></span></span>
</span>
</span>
</span>
這個時候,我們就明白了,原來我們可以在 UI視圖文件裏調用 effects 中的函數,而且函數的第一個形參就是我們手動傳入相關必要參數。
比如,我們要編寫登陸功能代碼,可以傳入 “用戶名”、“密碼”:
<div class="lake-codeblock-content"><div class="CodeMirror"><pre class="cm-s-default"><span class="lake-preview-line"><span class="lake-preview-line-number lake-lm-pad-level-0"></span><span class="lake-preview-codeblock-content"><span class="cm-meta">...</span>
dispatch({
type:‘user/login’,
payload:{ username:‘羽旋杯水’, password:‘123456’},
});
這個時候,我們就在 user.js 文件的 *login( { payload },{ call , put} ), 此時 payload = { username:'羽旋杯水', password:'123456'} ,將拿到的數據經過邏輯處理,就可以和後端進行交互了。
OK ,我現在來看第二個參數 effects ,它會在控制檯打印出什麼呢?
<span data-role="maximize" class="lake-image-editor-maximize" style="display: none;"><span class="lake-icon lake-icon-full-screen"></span></span>
</span>
</span>
</span>
從打印結果看,dva 預設的默認函數還是比較多的,但是我們比較常用 3 個,分別是:call ,put ,select
2、call、put、select 用法
那它們都代表什麼含義?怎麼使用呢?
call:用於調用異步邏輯,支持 promise 。
<div class="lake-codeblock-content"><div class="CodeMirror"><pre class="cm-s-default"><span class="lake-preview-line"><span class="lake-preview-line-number lake-lm-pad-level-0"></span><span class="lake-preview-codeblock-content"><span class="cm-comment">//call用法:</span>
//request :代表發送ajax請求
//payload :代表發送ajax請求時,所需要的參數
const res = yield call(request,payload);
put:用於觸發 action。
<div class="lake-codeblock-content"><div class="CodeMirror"><pre class="cm-s-default"><span class="lake-preview-line"><span class="lake-preview-line-number lake-lm-pad-level-0"></span><span class="lake-preview-codeblock-content"><span class="cm-comment">//put用法:</span>
//xx代表:models名
//jj代表:函數名
//res代表:所需的數據
yield put ({
type:‘xx/jj’,
payload:res
});
select:用於從 state 裏獲取數據。
<div class="lake-codeblock-content"><div class="CodeMirror"><pre class="cm-s-default"><span class="lake-preview-line"><span class="lake-preview-line-number lake-lm-pad-level-0"></span><span class="lake-preview-codeblock-content"><span class="cm-comment">//select用法:</span>
//data代表:所需要的數據
//其中state:代表所有models數據
const data = yield select(state=>state.data);
細心的小夥伴就有疑問了,每個關鍵字前面都有 yield ,yield的作用是什麼呢?
yield作用:保證當前語句執行完畢後,再執行下面的代碼。
二、reducers 內函數有什麼特點?
1、分析 reducers 函數形參
<div class="lake-codeblock-content"><div class="CodeMirror"><pre class="cm-s-default"><span class="lake-preview-line"><span class="lake-preview-line-number lake-lm-pad-level-1"></span><span class="lake-preview-codeblock-content"><span class="cm-meta">...</span>
reducers: {
show(state, { payload }) {
return {
state,
payload,
};
},
},
大多數情況下,我們只需要一個 show 函數就可以完成大部分業務需求了。
show 函數的第一個形參 state,就是我們的預設數據。
show 函數的第二個形參 action,就是我們傳過來的參數數據。
有些小夥伴不太理解其中 return 返回內容,我們就來分析一下吧。
分析之前,推薦閱讀:屬性展開
這裏的 return { ...state, ...payload },意思是將 payload 傳過來的數據,保存到預設 state 裏。所以當 state 數據發生改變後,頁面也會隨之重新渲染。
其實,effects 和 reducers 還是比較簡單的。大家理解了嗎?