乐趣区

Dva.js总结

1.why Dva
dva 是基于现有应用架构 (redux + react-router + redux-saga 等)的一层轻量封装,没有引入任何新概念,全部代码不到 100 行。dva 实现上尽量不创建新语法,而是用依赖库本身的语法,比如 router 的定义还是用 react-router 的 JSX 语法的方式(dynamic config 是性能的考虑层面,之后会支持)。他最核心的是提供了 app.model 方法,用于把 reducer, initialState, action, saga 封装到一起
app.model({
namespace: ‘products’,
state: {//State 表示 Model 的状态数据
list: [],
loading: false,
},
subscriptions: [
function(dispatch) {
dispatch({type: ‘products/query’});// 触发 action 的函数,action 是改变 State 的唯一途径
},
],
effects: {//Effect 被称为副作用,在我们的应用中,最常见的就是异步操作
[‘products/query’]: function*() {
yield call(delay(800));
yield put({
type: ‘products/query/success’,
payload: [‘ant-tool’, ‘roof’],
});
},
},
// 在 dva 中 reducers 聚合积累的结果是当前 model 的 state 对象。通过 actions 中传入的值,
// 与当前 reducers 中的值进行运算获得新的值(也就是新的 state)
reducers: {
[‘products/query’](state) {
return {…state, loading: true,};
},
[‘products/query/success’](state, { payload}) {
return {…state, loading: false, list: payload};
},
},
});
2. 简单明了的 Dva 数据流向
数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State

3.Dva Router 控制
dva 实例提供了 router 方法来控制路由,使用的是 react-router
const app = dva();
import {Router, Route} from ‘dva/router’;
app.router(({history}) =>
<Router history={history}>
<Route path=”/” component={HomePage} />
</Router>
);

4.dva 应用的最简结构(带 model)
// 创建应用
const app = dva();

// 注册 Model
app.model({
namespace: ‘count’,
state: 0,
reducers: {
add(state) {return state + 1},
},
effects: {
*addAfter1Second(action, { call, put}) {
yield call(delay, 1000);// 异步操作
yield put({type: ‘add’});// 类似于 dispatch 发 action
},
},
});

// 注册视图
app.router(() => <ConnectedApp />);

// 启动应用
app.start(‘#root’);

5.AntDesignPro1.0 项目中的 Dva
1.index.js
const app = dva({
history: createHistory(),//history 可以用来跳转路由内含 location 属性,这里修改 history 默认接口,其他接口不变 —- 初始化
});

// 2. Plugins
app.use(createLoading());// 加载插件这里应该加载的是加载动画插件

// 3. Register global model
app.model(require(‘./models/global’).default);// 将 src/modles 里面的东西灌进去,通过 namespace 取

// 4. Router
app.router(require(‘./router’).default);// 全局挂载路由信息

// 5. Start
app.start(‘#root’);

export default app._store;
2.router.js
export const getRouterData = app => {
const routerConfig = {
‘/’: {
component: dynamicWrapper(app, [‘user’, ‘login’], () => import(‘../layouts/BasicLayout’)),
},
‘/person/personbasetwo’: {// 添加路径指向引入的组件,这条数据会被 getRoutes 函数渲染成真正的 <Route> 包裹的路由
component: dynamicWrapper(app, [‘personbaseTwo’], () => import(‘../routes/Person/PersonBaseTwo’)),
},
‘/person/baseInfo/:id’: {//dynamicWrapper 函数会吧 [] 里面数据放到 app 的 model 属性里,app 是 dva 的实例
component: dynamicWrapper(app, [‘personbase’], () => import(‘../routes/Person/PersonBase/BaseInfo’)),
},
·······
3.connect 连接 model
/*dva 的实例 app 中应该导入了所有的 model,好像是在 router 中导入的,
这里用解构赋值从 model 中取值,为组件导入 props,loading 为 dva 提供的动画插件 */
@connect(({personbaseTwo, loading}) => ({
personbaseTwo,
searchLoading: loading.effects[‘personbaseTwo/getList’],
//loding 被这个异步函数影响,异步操作中就为 ture,结束就为 false
loading: loading.effects[‘personbaseTwo/listpage’],
}))// 从 model 中取数据生成自己想要的对象结构通过 @修饰器放到下面组件中去
class personbaseTwo extends Component {
constructor(props){
super(props);
this.state = {
}
}
componentWillMount(){// 组件将要渲染时拿到默认的一页多少条和当前页这些数据
const {personbaseTwo:{pagination} }= this.props;
const {page,pageSize} = pagination;
this.props.dispatch({// 转到 namespace 为 personbaseTwo 下面的 listpage 方法拿到页码为 page 的数据
type:’personbaseTwo/listpage’,// 接口根据 page 只去此页数据
payload:{
page,
pageSize,
},
});
}
·······
4. 跳转路由
onOk() {// 点击确定执行的函数
const {id}= record;
than.props.dispatch(routerRedux.push({// 用来跳转路由的
pathname: `/person/baseInfoTwo/${id}`,// 用这个 pathname 重新渲染路由页面并传 ID
}))
},

退出移动版