dva@2.4.1
dva 簡介
這裡就不過多冗餘了,引用官方文件的介紹:(詳細見:DvaJS - 介紹)
dva 首先是一個基於 redux 和 redux-saga 的資料流方案,然後為了簡化開發體驗,dva 還額外內建了 react-router 和 fetch,所以也可以理解為一個輕量級的應用框架。
本文目標
今天先了解一下 Dva 中的核心 Model,相信很多剛看 Dva 的同學對 Model 裡面的內容有點懵,今天我們主要就聊聊 Model。
問題:
namespace
是什麼?有什麼作用- Model中的
state
是什麼? - Model中的
reducers
物件裡定義的函式的兩個引數add (state, action)
是什麼?
我們基於官方的一個簡單例子——Count: 簡單計數器,改一下程式碼,嘗試讓其更容易理解
namespace 與 state
嘗試將上面連結中的程式碼換掉,使用附錄1的程式碼,然後開啟 Redux DevTools,對比一下修改前和修改後的區別,如下兩圖所示:
實際上,每定義一個 model,實際上就是在“資料樹”(最外面的物件)上掛一小塊,再嘗試將程式碼換成附錄2看看,如下圖
每定義一個 model,相當於在“資料樹”上定一個物件或者屬性
那麼 namespace
是什麼?——講到這裡就應該比較好理解了,namespace 只是“資料樹”這個物件的屬性名,如上圖的count
、school
、company
。這就是namespace
其中一個重要的作用。
namespace
另外一個的重要作用是告訴 dispatch
函式,到底要執行哪個 model 中的哪個函式。
還是回到 附錄1 的程式碼:
props.dispatch({
type: 'count/add',
payload: 1,
})
複製程式碼
這裡,實際上 type: 'count/add'
就是告訴dispatch
函式,需要執行count這個 model 中的add函式(ps:add 可以寫在reducers中,也可以寫在effects中,這個以後再講)
以上,解答了開頭的前兩個問題,到這裡應該對 namespace
和 Model 中的 state
不陌生了吧
reducers
來,我們再看看第三個問題,到底 reducers
物件裡定義的函式的兩個引數add (state, action)
是什麼?
請看附錄1的程式碼:
reducers: {
add (state, action) {
let num = state.num + action.payload;
return {
...state,
num,
};
},
},
複製程式碼
第一個引數(state),指的是當前這個 model的 state 的值(附錄1的是namespace: 'count'
這個 model)。如果什麼事情都沒發生,那麼此時的值應該是初始值,即:
{
flag: '我是一個擺設',
num: 0,
},
複製程式碼
第二個引數(action),指的是dispatch 函式的引數(整個物件):
props.dispatch({
type: 'count/add',
payload: 1,
})
複製程式碼
這時可以嘗試把程式碼換成附錄3,點一下加號,看看列印出來的是什麼
到這裡應該已經清晰這兩個引數到底是什麼了
但是還有一個問題,就是為什麼 add 函式的 return 要寫成:
return {
...state,
num,
};
複製程式碼
細心的你應該不難發現,這裡就留一個探索題,試試把 ...state,
,去掉,然後執行一下附錄1的程式碼,檢視一下 Redux DevTools,你肯定可以發現有什麼不妥。
一個小提示:
...state
是 ES6物件的擴充套件運算子
附錄1
import React from 'react';
import dva, { connect } from 'dva';
import './style.css';
// 1. Initialize
const app = dva();
// 2. Model
app.model({
namespace: 'count',
state: {
flag: '我是一個擺設',
num: 0,
},
reducers: {
add (state, action) {
let num = state.num + action.payload;
return {
...state,
num,
};
},
},
});
// 3. View
const App = connect(({ count }) => ({
count
}))(function(props) {
return (
<div>
<h2>{ props.count.num }</h2>
<button key="add" onClick={() => {
props.dispatch({
type: 'count/add',
payload: 1,
})
}}>+</button>
</div>
);
});
// 4. Router
app.router(() => <App />);
// 5. Start
app.start('#root');
複製程式碼
附錄2
import React from 'react';
import dva, { connect } from 'dva';
import './style.css';
// 1. Initialize
const app = dva();
// 2. Model
app.model({
namespace: 'count',
state: {
flag: '我是一個擺設',
num: 0,
},
reducers: {
add (state, action) {
let num = state.num + action.payload;
return {
...state,
num,
};
},
},
});
app.model({
namespace: 'school',
state: {
flag: '我是一個擺設,我在 school 這個 model 中',
},
reducers: {
},
});
app.model({
namespace: 'company',
state: {
flag: '我是一個擺設,我在 company 這個 model 中',
},
reducers: {
},
});
// 3. View
const App = connect(({ count }) => ({
count
}))(function(props) {
return (
<div>
<h2>{ props.count.num }</h2>
<button key="add" onClick={() => {
props.dispatch({
type: 'count/add',
payload: 1,
})
}}>+</button>
</div>
);
});
// 4. Router
app.router(() => <App />);
// 5. Start
app.start('#root');
複製程式碼
附錄3
import React from 'react';
import dva, { connect } from 'dva';
import './style.css';
// 1. Initialize
const app = dva();
// 2. Model
app.model({
namespace: 'count',
state: {
flag: '我是一個擺設',
num: 0,
},
reducers: {
add (state, action) {
let num = state.num + action.payload;
console.log(action);
return {
...state,
num,
};
},
},
});
// 3. View
const App = connect(({ count }) => ({
count
}))(function(props) {
return (
<div>
<h2>{ props.count.num }</h2>
<button key="add" onClick={() => {
props.dispatch({
type: 'count/add',
payload: 1,
extra: {
name: 'wuqinfa',
age: 18
}
})
}}>+</button>
</div>
);
});
// 4. Router
app.router(() => <App />);
// 5. Start
app.start('#root');
複製程式碼
作者簡介:吳勤發,蘆葦科技web前端開發工程師。擅長網站建設、公眾號開發、微信小程式開發、小遊戲、公眾號開發,專注於前端框架、服務端渲染、SEO技術、互動設計、影象繪製、資料分析等研究,有興趣的小夥伴來撩撩我們~ web@talkmoney.cn
訪問 www.talkmoney.cn 瞭解更多