当前位置:网站首页>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.12、创建项目
$ dva new dva-1 //dva-1 为你创建项目的名称cddva-1npm startyarn startnpm iyarn3、使用 antd
$ npm install antd babel-plugin-import --savenpmantdbabel-plugin-importbabel-plugin-importantd.webpackrcbabel-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,
});initialStateinitialStateinitialStatemodelstateinitialStatemodelnamespce(2)、装载插件
loadingshowloadinghideloading(3)、注册 Model
modelindex.jsmodel(4)、配置路由
index.jsrouter.js(5)、启动应用
2、router.js
router.jsimport 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>使用
pathcomponenthome解释一下
historylocationlocationreact-routerreact router3、components 包
4、routes 包
pages5、services 包
6、utils 包
js6、models 包
modelsmodelmodelexport defalut {
namespace:'',
state:{},
reducers:{},
effects:{},
subscriptions:{},
}Model四、Model 包下文件架构(重点)
1、namespace
namespacejshome.jsnamespacehome2、state
this.props3、reducers
actionreducersstateexample.jsreducersreducers: {
save1(state, action) {
return { ...state, ...action.payload };
},
save2(state, action) {
return { ...state, ...action.payload };
},
},(1)、save
save(2)、state
statestateconsole.log(state)(3)、action
actionactionactionstate(4)、payload
payloadactionconsole.log(action.payload)(5)、return
returnstatestatereturnstatestatestatestate...statereturnstate4、effects
effectsreducersstateimport { 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
payloadactionactionstatepayloadactionconsole.log(payload)(4)、call
calldataconsole.log(data)(5)、put
putactionreducerstypereducerspayloadreducers(6)、select
selectselectconst homeName = yield select(state => state.home);homestate(5)、subscription
subscriptionsubscriptions: {
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 页面下的数据
dvaconnectimport { connect } from 'dva';class ~ extends React.Componentsconnectexport default connect(({index}) => ({index}))(IndexPage);indexindexnamespace六、初始化数据 和 Model 数据比对
1、初始化数据
index.jsinitialStatemodelnamespace2、Model -> state
initialStatemodelstate{}initialState七、数据显示和操作的流程
1、编写 Route 页面
classclass ~ 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 };
},
},
};Model3、编写 初始化数据
index.jsconst 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 连接
Routeexample.jsconnectimport { connect } from 'dva';
export default connect(({ example }) => ({ example }))(Example);this.propsexample6、前台调用 Model 层方法
dispatchdispatchactionModeldispatchconst { dispatch } = this.props; //在 dva 中,可以通过 `this.props` 直接取得 `dispatch`
dispatch ({
type:'example/fetch', //指定哪个 model 层里面的哪个 方法
payload:{name:'exampleNew'}, //需要传递到 model 层里面的参数。dayload 为固定用法(我自己的理解)。
})typeexample/savereducer7、数据在 Model 中的流向
console.log(dayload)const data = yield call(接口名,参数名);console.log(data)yield put({ type:'save',payload:data })reducerreducersreturnstate八、稍复杂概念
1、多次调用
effectputreducereffectcall2、多任务调度
- 并行。若干任务之间不存在依赖关系,并且后续操作对他们的结果无依赖。
- 竞争。只有一个完成,就进入下一个环节。
- 子任务。若干任务,并行执行,全部做完之后,才能进入下一个环节。
并行
const [ result1,result2 ] = yield [
call(service1,param1),
call(service2,param2),
]竞争
const { result1,result2 } = yield race({
result1:call(service1,param1),
result2:call(service2,param2),
})子任务
多次调用边栏推荐
- Spinner文字显示不全解决办法
- 出色的移动端用户验证
- [Star Project] Little Hat Plane Battle (9)
- CADEditorX ActiveX 14.1.X
- Web Server 设置缓存响应字段的一些推荐方案
- GBase 8c与openGauss是什么关系?
- Mysql OCP 73 questions
- numpy
- [LeetCode—Question 2 Sum of Two Numbers Detailed Code Explanation ] The source code is attached, which can be copied directly
- 程序员架构修炼之道:如何设计出可持续演进的系统架构?
猜你喜欢

Who is more popular for hybrid products, depending on technology or market?

How to retrieve IDC research reports?

【LeetCode—第2题 两数之和 代码详解 】附有源码,可直接复制

4 g acquisition ModbusTCP turn JSON MQTT cloud platform

嵌入式软件组件经典架构与存储器分类

Depth study of 100 cases - convolution neural network (CNN) to realize the clothing image classification

程序员架构修炼之道:软件架构基本概念和思维

synchronized

「全球数字经济大会」登陆 N 世界,融云提供通信云服务支持

Polymorphism in detail (simple implementation to buy tickets system simulation, covering/weight definition, principle of polymorphism, virtual table)
随机推荐
Guys, I have a problem: My source mysql has a table that has been writing to, I use mysql cdc connec
优炫数据库在linux平台下服务启动失败的原因
关于OPENSSL的问题
oracle计算同、环比
成为优秀架构师必备技能:怎样才能画出让所有人赞不绝口的系统架构图?秘诀是什么?快来打开这篇文章看看吧!...
袋鼠云思枢:数驹 DTengine,助力企业构建高效的流批一体数据湖计算平台
Mysql OCP 75 questions
Depth study of 100 cases - convolution neural network (CNN) to realize the clothing image classification
跨链桥协议 Nomad 遭遇黑客攻击,损失超 1.5 亿美元
鸿蒙第四次
一文带你弄懂 CDN 技术的原理
Skills required to be a good architect: How to draw a system architecture that everyone will love?What's the secret?Come and open this article to see it!...
干货!一种被称为Deformable Butterfly(DeBut)的高度结构化且稀疏的线性变换
How to retrieve IDC research reports?
Why is the new earth blurred, in-depth analysis of white balls, viewing pictures, and downloading problems
巴比特 | 元宇宙每日必读:玩家离场,平台关停,数字藏品市场正逐渐降温,行业的未来究竟在哪里?...
3分钟实现内网穿透(基于ngrok实现)
numpy
LyScript 实现对内存堆栈扫描
numpy