React 之 dva

作者 糖一瓶 日期 2018-04-02
React 之 dva

什么是dva?

dva集成了react + redux + saga , 让这三个东西看起来更加的“统一”,大变了语法风格和整个项目的架构。

基本使用

先来一份目录结构:

test
  |-www
     |-index.html
     |-app
       |-App.js
       |-main.js
  |-package.json
  |-webpack.config.js

1.起步

dva的起步非常简单:
1)要创建一个app对象,非常类似express
2)用app.router定义一个路由
3)用app.start()来上树。
main.js代码如下:

import React from "react";
import ReactDOM from "react-dom";
import dav from "dva"
const app = dva();

app.router(()=>{
return <h1>Hello dva</h1>
});
app.start("app");

2.组件

组件没有改变,所以组件的生命周期也没有改变,组件的state、props都没有任何改变。

3.配置store

我们知道redux就是全局的数据中心,dva全面简化了这一套东西。
创建models文件夹,创建counter.js文件:
目录结构如下:


test
|-www
|-index.html
|-app
|-App.js
|-main.js
|-models
|-.counter.js
|-package.json
|-webpack.config.js

export default {
//必须有命名空间
namespace : "counter" ,
state : {
v : 100
}
}

即,我们之前的reducers里面的

export default (state= {"v" : 100} , action){

}

这套东西现在变为了一个纯对象,我们称为model。
model必须有namespace,表示命名空间,就是原来说的combineReducers的命名空间。

 在main.js中引入数据
main.js:

import React from "react";
import dva from "dva";

import App from "./App.js";
// 引入数据
import counter from "./models/counter.js";

//创建app
const app = dva();
//配置store
app.model(counter);
//配置路由
app.router(() => <App />);
//上树
app.start("#app");

组件几乎没有改变得到值的写法,还是需要connect,但是需要从dva中引包:

import React from "react";
import {connect} from "dva";

class App extends React.Component{
constructor(){
super();
}

render(){
return <div>
<h1>{this.props.v}</h1>
</div>
}
}

export default connect(
({counter}) => ({
v: counter.v
})
)(App);

dva帮我们combineReducers了。

4.dispatch一个action

全面简化了!
现在组件可以直接this.props.dispatch()东西了。而不用调用一个外置的action文件了,更不用bindActionCreators了。

import React from "react";
import {connect} from "dva";

class App extends React.Component{
constructor(){
super();
}

render(){
return <div>
<h1>{this.props.v}</h1>
<button onClick={()=>{
this.props.dispatch({"type" : "counter/ADD"});
}}>按我加1</button>
<button onClick={()=>{
this.props.dispatch({"type" : "counter/MINUS"});
}}>按我减1</button>
</div>
}
}

export default connect(
({counter}) => ({
v: counter.v
})
)(App);

dva中connect()()没有第二个参数!!!
dispatch里面的内容是{“type” : “命名空间/大写字母” , 载荷}

5.异步

dva中saga自动运行,自动拦截!
model文件中:

  1. reducers里面写没有副作用,类似之前的reducers文件。
  2. effects里面写有副作用的东西,都是加星函数,类似之前的saga文件。
    即,saga文件现在和reducer合二为一了。
    export default {
    namespace : "counter" ,
    state : {
    v : 100
    },
    reducers : {
    ADD(state , action){
    return {
    ...state ,
    "v" : state.v + (action.a || 1)
    }
    },
    MINUS(state , action){
    return {
    ...state,
    "v" : state.v - 1
    }
    }
    },
    effects : {
    *ADDSERVER(action , {put}){
    const {a} = yield fetch("/api/api").then(data=>data.json());
    yield put({ "type": "ADD" , a});
    },
    *JBOBB(action , {put , select}){
    const {v} = yield select(state => state.counter);
    if(v % 2 == 1){
    yield put({ "type": "ADD"});
    }
    }
    }
    }