当前位置:网站首页>Dva.js 新手入门指南
Dva.js 新手入门指南
2022-08-03 10:56:00 【InfoQ】
- 一、介绍
- 二、环境搭建和使用
- 三、全局架构
- 四、Model 包下文件架构
- 五、connect 连接 Model 和 Route 页面下的数据
- 六、初始化数据 和 Model 数据比对
- 七、数据显示和操作的流程
- 八、稍复杂概念
一、介绍
1、什么是 Dva
2、Dva 解决的问题
- 文件切换问题。redux 的项目通常要分 reducer, action, saga, component 等等,他们的分目录存放造成的文件切换成本较大。
- 不便于组织业务模型 (或者叫 domain model) 。比如我们写了一个 userlist 之后,要写一个 productlist,需要复制很多文件。
- saga 创建麻烦,每监听一个 action 都需要走 fork -> watcher -> worker 的流程
- entry 创建麻烦。可以看下这个redux entry的例子,除了 redux store 的创建,中间件的配置,路由的初始化,Provider 的 store 的绑定,saga 的初始化,还要处理 reducer, component, saga 的 HMR 。这就是真实的项目应用 redux 的例子,看起来比较复杂。
3、Dva 的优势
- 易学易用,仅有 6 个 api,对 redux 用户尤其友好,配合 umi 使用后更是降低为 0 API
- elm 概念,通过 reducers, effects 和 subscriptions 组织 model
- 插件机制,比如dva-loading可以自动处理 loading 状态,不用一遍遍地写 showLoading 和 hideLoading
- 支持 HMR,基于babel-plugin-dva-hmr实现 components、routes 和 models 的 HMR
4、Dva 的劣势
- 未来不确定性高。[email protected] 前年提出计划后,官方几乎不再维护。
二、环境搭建和使用
1、环境搭建
$ npm install dva-cli -g
$ dva -v //查看下是否安装成功,显示 dva 的版本号
dva-cli version 0.9.1
2、创建项目
$ dva new dva-1 //dva-1 为你创建项目的名称
cd
dva-1
npm start
yarn start
npm i
yarn
3、使用 antd
$ npm install antd babel-plugin-import --save
npm
antd
babel-plugin-import
babel-plugin-import
antd
.webpackrc
babel-plugin-import
{
+ "extraBabelPlugins": [
+ ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
+ ]
}
.
├── mock // mock数据文件夹
├── node_modules // 第三方的依赖
├── public // 存放公共public文件的文件夹
├── src // 最重要的文件夹,编写代码都在这个文件夹下
│ ├── assets // 可以放图片等公共资源
│ ├── components // 就是react中的木偶组件
│ ├── models // dva最重要的文件夹,所有的数据交互及逻辑都写在这里
│ ├── routes // 就是react中的智能组件,不要被文件夹名字误导。
│ ├── services // 放请求借口方法的文件夹
│ ├── utils // 自己的工具方法可以放在这边
│ ├── index.css // 入口文件样式
│ ├── index.ejs // ejs模板引擎
│ ├── index.js // 入口文件
│ └── router.js // 项目的路由文件
├── .eslintrc // bower安装目录的配置
├── .editorconfig // 保证代码在不同编辑器可视化的工具
├── .gitignore // git上传时忽略的文件
├── .roadhogrc.js // 项目的配置文件,配置接口转发,css_module等都在这边。
├── .roadhogrc.mock.js // 项目的配置文件
└── package.json // 当前整一个项目的依赖
1、index.js(重点)
import dva from 'dva';
// 1、创建 dva 实例
const app = dva();
// 2、装载插件 (可选)
app.use(require('dva-loading')());
// 3、注册 Model
app.model(require('./models/example'));
// 4、配置路由
app.router(require('./router'));
// 5、启动应用
app.start('#root');
(1)、创建 dva 实例
const app = dva({
history,
initialState,
onError,
onAction,
onStateChange,
onReducer,
onEffect,
onHmr,
extraReducers,
extraEnhancers,
});
initialState
initialState
initialState
model
state
initialState
model
namespce
(2)、装载插件
loading
showloading
hideloading
(3)、注册 Model
model
index.js
model
(4)、配置路由
index.js
router.js
(5)、启动应用
2、router.js
router.js
import IndexPage from './routes/IndexPage';
import HomePage from './routes/HomePage';
<Router history={history}>
<Switch>
<Route path="/" exact component={IndexPage} />
.
.
.
<Route path="/home" exact component={HomePage} />
</Switch>
</Router>
使用
path
component
home
解释一下
history
location
location
react-router
react router
3、components 包
4、routes 包
pages
5、services 包
6、utils 包
js
6、models 包
models
model
model
export defalut {
namespace:'',
state:{},
reducers:{},
effects:{},
subscriptions:{},
}
Model
四、Model 包下文件架构(重点)
1、namespace
namespace
js
home.js
namespace
home
2、state
this.props
3、reducers
action
reducers
state
example.js
reducers
reducers: {
save1(state, action) {
return { ...state, ...action.payload };
},
save2(state, action) {
return { ...state, ...action.payload };
},
},
(1)、save
save
(2)、state
state
state
console.log(state)
(3)、action
action
action
action
state
(4)、payload
payload
action
console.log(action.payload)
(5)、return
return
state
state
return
state
state
state
state
...state
return
state
4、effects
effects
reducers
state
import { querySomething } from '@/services/api';
*query({ payload }, { call, put, select }) {
const data = yield call(querySomething, payload);
console.log(data)
yield put({
type: 'save1',
payload: { name: data.text },
});
},
1)、*
*
*
effects
*
yield
(2)、query
query
(3)、payload
payload
action
action
state
payload
action
console.log(payload)
(4)、call
call
data
console.log(data)
(5)、put
put
action
reducers
type
reducers
payload
reducers
(6)、select
select
select
const homeName = yield select(state => state.home);
home
state
(5)、subscription
subscription
subscriptions: {
setup:({ dispatch, history }) {
window.onresize = () => { //这里表示的当浏览器的页面的大小变化时就会触发里面的dispatch方法,这里的save就是reducers中的方法名
dispatch (type:"save")
}
},
onClick ({dispatch}) {
document.addEventListener('click',() => { //这里表示当鼠标点击时就会触发里面的dispatch命令,这里的save就是reducers中的方法名
dispatch (type:"save")
})
}
五、connect 连接 Model 和 Route 页面下的数据
dva
connect
import { connect } from 'dva';
class ~ extends React.Components
connect
export default connect(({index}) => ({index}))(IndexPage);
index
index
namespace
六、初始化数据 和 Model 数据比对
1、初始化数据
index.js
initialState
model
namespace
2、Model -> state
initialState
model
state
{}
initialState
七、数据显示和操作的流程
1、编写 Route 页面
class
class ~ extends React.Component{}
import React from 'react';
const Example = ({dispatch,全局 `index.js` 里你需要的参数对象名称}) => {
return (<div></div>)
}
export default Example;
2、编写 Model 层代码
export default {
namespace: 'example',
state: {},
effects: {
*fetch({ payload }, { call, put }) { // eslint-disable-line
yield put({ type: 'save',payload:data });
},
},
reducers: {
save(state, action) {
return { ...state, ...action.payload };
},
},
};
Model
3、编写 初始化数据
index.js
const app = dva({
initialState: {
example: {
name:'nameText'
}
}
})
app.model(require('./models/example').default); //还要记得补上这句话。在 index.js 里载入它。
4、修改路由配置
import Count from './routes/Example';
<Route path="/example" exact component={Example} />
5、使用 connect 连接
Route
example.js
connect
import { connect } from 'dva';
export default connect(({ example }) => ({ example }))(Example);
this.props
example
6、前台调用 Model 层方法
dispatch
dispatch
action
Model
dispatch
const { dispatch } = this.props; //在 dva 中,可以通过 `this.props` 直接取得 `dispatch`
dispatch ({
type:'example/fetch', //指定哪个 model 层里面的哪个 方法
payload:{name:'exampleNew'}, //需要传递到 model 层里面的参数。dayload 为固定用法(我自己的理解)。
})
type
example/save
reducer
7、数据在 Model 中的流向
console.log(dayload)
const data = yield call(接口名,参数名)
;
console.log(data)
yield put({ type:'save',payload:data })
reducer
reducers
return
state
八、稍复杂概念
1、多次调用
effect
put
reducer
effect
call
2、多任务调度
- 并行。若干任务之间不存在依赖关系,并且后续操作对他们的结果无依赖。
- 竞争。只有一个完成,就进入下一个环节。
- 子任务。若干任务,并行执行,全部做完之后,才能进入下一个环节。
并行
const [ result1,result2 ] = yield [
call(service1,param1),
call(service2,param2),
]
竞争
const { result1,result2 } = yield race({
result1:call(service1,param1),
result2:call(service2,param2),
})
子任务
多次调用
边栏推荐
- 通过GBase 8c Platform安装数据库集群时报错
- 孙宇晨式“溢价逻辑”:不局限眼前,为全人类的“星辰大海”大胆下注
- Enter the SQL Client to create the table, in another node into the SQL Client queries
- 507. 完美数
- 图新地球为什么很模糊,白球、看图、下载问题深度剖析
- [Star Project] Little Hat Plane Battle (9)
- 使用.NET简单实现一个Redis的高性能克隆版(一)
- 【输出一个整数的的每一位,由高到低输出。使用递归和不使用递归】
- MapReduce中ETL数据清洗案例
- SAP 电商云 Spartacus UI 的 External Routes 设计明细
猜你喜欢
QT with OpenGL(Shadow Mapping)(面光源篇)
MySQL数据库实战(1)
如何检索IDC研究报告?
For invoice processing DocuWare, cast off the yoke of the paper and data input, automatic processing all the invoice received
成为优秀架构师必备技能:怎样才能画出让所有人赞不绝口的系统架构图?秘诀是什么?快来打开这篇文章看看吧!...
Web Server 设置缓存响应字段的一些推荐方案
CADEditorX ActiveX 14.1.X
What is the relationship between The Matrix and 6G?
Depth study of 100 cases - convolution neural network (CNN) to realize the clothing image classification
[Detailed explanation of binary search plus recursive writing method] with all the code
随机推荐
通过GBase 8c Platform安装数据库集群时报错
type="module" you know, but type="importmap" you know
机器比人更需要通证
混动产品谁更吃香,看技术还是看市场?
Activiti产生的背景和作用
3分钟实现内网穿透(基于ngrok实现)
二叉搜索树(搜索二叉树)模拟实现(有递归版本)
Question G: Word Analysis ← Questions for the second provincial competition of the 11th Blue Bridge Cup Competition
如何改变sys_guid() 返回值类型
机器学习(公式推导与代码实现)--sklearn机器学习库
Machines need tokens more than people
Dry goods!A highly structured and sparse linear transformation called Deformable Butterfly (DeBut)
【TypeScript】为什么要选择 TypeScript?
Machine Learning (Chapter 1) - Feature Engineering
BPMN和DMN基本概念和使用案例
关于OPENSSL的问题
Interview Blitz 71: What's the difference between GET and POST?
数字藏品和ICP
鸿蒙第四次
Spinner文字显示不全解决办法