使用场景
dva 首先是一个基于 redux 和 redux-saga 的数据流方案.
dva 也是 React 应用框架,同样包装了React-Router,简化了 API,让开发 React 应用更加方便和快捷。
所以:
dva = React-Router + Redux + Redux-saga
快速上手
1、dva提供了一套自己的脚手架 用于构建一个基于dva的基础框架
$ npm install dva-cli -g
$ dva -v
dva-cli version > 0.9.1
$ dva new dva-quickstart
2、也可以只使用 dva 单纯的当做一个状态管理工具
$ npm i dva
// 普通项目中使用dva
import dva from 'dva';
const app = dva();
app.router(() =>
<App />
);
app.start('#root');
dva(opts)可配置opts有哪些?[1]
核心概念
img2.jpgState 和 View
-
State:一个对象,保存整个应用状态
State 是储存数据的地方,收到 Action 以后,会更新数据。
-
View:React 组件构成的视图层
View 就是 React 组件构成的 UI 层,从 State 取数据后,渲染成 HTML 代码。只要 State 有变化,View 就会自动更新。
Action
- Action:用来描述 UI 层事件的一个对象
{ type: 'click-submit-button', payload: this.form.data }
connect
- connect 方法:一个函数,绑定 State 到 View
import { connect } from 'dva'; //函数会返回一个对象,用于建立 State 到 Props 的映射关系。 function mapStateToProps(state) { return { todos: state.todos }; } connect(mapStateToProps)(App); //返回一个React 组件,App通常是个最外层的容器组件,相当于在整个项目包了一层state
dispatch
- Action 处理器:处理同步操作的函数。触发 Action 改变 State
dispatch({ type: 'click-submit-button', payload: this.form.data })
dispatch 方法从哪来?被 connect 的 Component 会自动在 props 中拥有 dispatch 方法。
Effect
-
Action 处理器;处理异步操作的函数。对象中定义 Generator[2] 函数
effects: { // 这里定义 Generator 函数【es6】 // dva 提供多个 effect 函数内部的处理函数,比较常用的是 call 和 put。 *addAfter1Second(action, { call, put, select }) { // const result = yield call(timeoutfun, action.payload); const result = yield (timeoutfun(action.payload)); console.log('我是call 的 result', result); const todos = yield select(state => state.count.todos);//此处count为自定义的namespace值 console.log('我是select 的 todos', todos); const newState = yield put({ type: 'addTodo', payload: todos }); console.log('我是put 的 newState', newState); }, }
- call 用于调用异步逻辑,支持 promise
- select 用于从 state 里获取数据,返回相应的数据
- put 用于触发 Action,类似于 dispatch 处理同步逻辑
Subscription
- 监听器其中,其中方法名可随意定义。初始化必会自动调用一次,每次变化都会⼀次去调⽤⾥⾯的所有⽅法。
subscriptions: {
watch({ dispatch, history }, error) {
return history.listen(({ pathname, query }) => {
console.log(pathname)
console.log(query)
});
},
click({ dispatch, history }, error) {
document.addEventListener('click', () => {
//只要⿏标点击就会dispatch,这⾥的add就是reducers中的⽅法名
dispatch({ type: "add" })
})
}
}
Model
dva 提供 app.model 这个对象,所有的应用逻辑都定义在它上面
model 是 dva 中最重要的概念。以下是典型的例子:
{
namespace: 'count',
// 初始化值 优先级低于dva() 的 opts.initialState
state: {
todos:3000
},
reducers: {
// Action 处理器;处理同步操作的函数,根据 Action,从上一个 State 算出当前 State。
add(state) { return state + 1 },
// 往 [] 里添加一个新 todo
addTodo(state, action) { return {...state, payload:action.payload}; }
},
effects: {
*addAfter1Second(action, { call, put, select }) {
// const result = yield call(timeoutfun, action.payload);
const result = yield (timeoutfun(action.payload));
console.log('我是call 的 result', result);
const todos = yield select(state => state.count.todos);//此处count为自定义的namespace值
console.log('我是select 的 todos', todos);
const newState = yield put({
type: 'addTodo',
payload: todos
});
console.log('我是put 的 newState', newState);
},
},
subscriptions: {
watch({ dispatch, history }, error) {
return history.listen(({ pathname, query }) => {
console.log(pathname)
console.log(query)
});
},
click({ dispatch, history }, error) {
document.addEventListener('click', () => {
dispatch({ type: "add" })
})
}
}
}
- namespace: 当前 Model 的名称。dva可以有多个model 以namespace进行区分调用
- state: 当前 Model 保存state数据的变量
- reducers: 处理同步动作,唯一可以修改 state 的地方。由 action 触发。
- effects:Action 处理器,处理异步动作
-
ES6 新引入了 Generator 函数,函数内用 yield 标记同步逻辑,函数实例使用 .next()依次调用。从而解决异步问题。 ↩
网友评论