DVA学习

1 篇文章 0 订阅

一,什么是Dva?

1.react专注于ui渲染,功能较为单一,在实际开发一个react项目需要更多库的支持,例如在react项目中最常用的数据状态管理器reduxredux-saga,路由控制react-router等等。

2.Dva 是轻量级的 React应用框架,将ReduxReact-RouterRedux-saga 三个 React 工具库整合在一起,简化了api,让开发更便捷。

3.我们可以简单的理解,Dva = react-router + rudex + redux-saga ,没有更多的功能,但是有更简洁的api

4.官方文档

二,创建一个Dva项目

1.官方提供了脚手架dva-cli,用于创建一个Dva项目

2.首先使用包管理工具npm安装脚手架: npm install dva-cli -g

3.之后使用 dva new [projectName] 命令来创建一个dva项目

三,Dva项目结构

1.使用dva-cli创建的项目默认的项目结构如下图所示

在这里插入图片描述

四,Dva入口文件

1.在Dva项目的入口文件,完成了

(1)路由的注册
(2)model的注册
(3)插件的注册
(4)项目启动

2.入口文件几乎涉及了Dva的所有api

import dva from 'dva'; //dva库默认export一个dva函数,用于创建dva实例
import './index.less';
import createLoading from 'dva-loading';

// 1. 初始化
const app = dva();  

// 2. 插件
app.use(createLoading());  //use方法用于使用插件,和注册hooks

// 3. 注册model
app.model(require('./models/example').default);  //model`方法接受一个model对象,用于注册model
app.model(require('./models/others').default);
...

// 4. 注册路由
app.router(require('./router').default); //router方法接受一个具有固定格式的函数,用于注册路由表

// 5. 项目启动
app.start('#root');

3.关于更多api详情可以查看官方文档

五,定义路由

1.在Dva项目里,默认的我们在src文件夹下的router.js文件定义路由。

import React from 'react';
import { Router, Route, Switch } from 'dva/router';  //路由相关的组件在dva/router中

import IndexPage from './routes/IndexPage';

function RouterConfig({ history }) {
  return (
    <Router history={history}>
      <Switch>
        <Route path="/" exact component={IndexPage} />
      </Switch>
    </Router>
  );
}

export default RouterConfig;

2.我们可以使用dva/dynamic来做代码分割,动态注册model,提高首屏加载速度

import React from 'react';
import { Router, Route, Switch } from 'dva/router';  //路由相关的组件在dva/router中
import dynamic from 'dva/dynamic'

const routes =[
{	path:'/', 
	component: ()=>import('./routes/Example'),
	model:()=>[import('./models/example')]
}
]
import IndexPage from './routes/IndexPage';

function RouterConfig({ history,app }) {
  return (
    <Router history={history}>
      <Switch>
      {routes.map(({path,...dynamic})=><Route path={path} exact component{dynamic({app,...dynamic})} />)}
      </Switch>
    </Router>
  );
}

export default RouterConfig;

六,定义model

1.在Dva项目中,我们在models文件夹下定义model

2.一个基本的model如下


export default {

  namespace: 'example', //model的命名

  state: {
  	text:'hello dva', //定义数据的地方,数据的改变是响应式的
  },

  subscriptions: { //订阅数据源,相当于一个监听器,可以监听路由变化,鼠标,键盘变化,服务器连接变化,状态变化等
    setup({ dispatch, history }) { //监听路由变化实例
    	history.listen(({ pathname }) => {
           if (pathname === '/xxx') {
           	//do something	
            }
        });  
    },
  },

  effects: {
    *fetch({ payload }, { call, put, select,all }) { //effects里的函数是es6中的generator函数, 用于定义异步操作
      yield put({ type: 'save' }); //put类似于dispatch,用于触发action
      yield call(service,params) //call可用于请求服务端
      yield select(state=>state.example>) //select用于获取model里的数据,要在effects函数中使用state数据,必须使用select**。
      yield all([]) //类似于Promise的Promise.all([])
    },
  },

  reducers: {
    save(state, action) {  //reducers函数的第一个参数是该model的state,action是触发的动作,包含了传递了参数
      return { ...state, ...action.payload }; //reducers函数返回的值作为最新的state
    },
    updateState(state, {payload}){ //通常我们只需要action里的负荷载体,因此可直接解构出来
      return { ...state, ...action.payload };
    },
  },
};

3.可以看出 model是一个对象,包含了5个选项,其中除了namespacestate是必须定义的,其他的是可选项

(1)namespace : 接收一个字符串表示model 的命名空间,同时也是他在全局 state 上的属性

(2)state : 接收一个对象表示状态初始值,优先级低于传给 dva()opts.initialState

(3)subscriptions : 订阅数据源

(4)effects : 接收一个对象定义异步操作,如请求服务端服务

(5)reducers : 接收一个对象定义同步操作,唯一可以 修改 state 的地方

七,将modelUI组件关联

1.在定义了model,并且注册了model(在入口文件,或者注册路由时动态引入),最后一步还需modelUI组件关联起来

2.dvaexport了一个高阶组件connect用于将modelUI组件关联。

import { connect } from 'dva';

3.connect是一个函数,接受两个函数作为参数,并且返回一个函数,返回的函数接受一个组件作为参数,返回连接了state的包装后的组件

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

function Example(props){
	return <div></div>
}

const mapStateToProps =state=>({example:state.example}) 
export default connect(mapStateToProps,mapDispatchToProps)(Example);
//或者
export default connect(({example})=>({example}))(Example);

4.第一个函数mapStateToProps 用于建立state和组件props的对应关系,其中参数state包含了所有全局注册的model和注册路由时动态导入的model

5.被connect之后的组件props返回值如下

(1)包含了dispatch用于触发action
(2)连接了modelstate,如下的example

在这里插入图片描述

八,完整数据流

1.数据的改变发生通常是通过用户交互行为或者浏览器行为触发的。当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State
在这里插入图片描述

2.从上图不难发现 dispatch是用于发起 数据改变的唯一方法,触发源可以在UI组件中,如某次点击事件需要改变state,或者触发源可以在subscription中,例如当我们使用subscription监听到路由变化时,初始化state

3.dispatch接受一个action , action描述一个行为,包含typepayload

(1)type是指定的动作,即model中定义的reducerseffects
(2)payload是载体,用于承载参数

let action = { type:'example/save', payload:{ text:'hello dva again'}}

<div onClick={()=>dispatch(action)}></div>

4.当用dispatch触发一个副作用effects时,返回的是一个Promise

九,loading对象,

1.dva框架内置了loading插件,我们可以在全局中import后使用。

import createLoading from 'dva-loading';
 const app = dva(createLoading());

这样在所有的组件中都可以使用loading对象。

2.具体用法,用于异步操作,在异步操作开始时为true,结束时为false

export default connect(
  ({
    userAndlogin,
    loading,
  }) => ({
    userAndlogin,
    submitting: loading.effects['userAndlogin/login'],
  }),
)(Login);
  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值