基于react+redux的轻量级框架dva初使用及应用逻辑分析
来源:互联网 发布:软件开发做账 编辑:程序博客网 时间:2024/06/10 14:55
随着React的大火,flux架构也跟着火了起来,Redux是实现flux架构的库中的佼佼者,使用react+redux来开发应用的开发者也越来越多
确实,React+Redux+webpack+babel+es6,这是一个极具生产力的组合
源自flux架构的单向流动使得应用的逻辑和数据流动变得可控,当应用逻辑变得复杂的时候,其优势越加明显,开发越加高效
但是在开发的时候出现了一些问题,比如说概念太多,文件太松散等等问题
以及为了解决异步交互问题,会引用一些中间件来处理store,比较常见的是用thunk中间件+asysc或者用saga等等
图为一个中间件处理store的代码
这不是Dva解决的最大的问题,Dva的重点是引进了model这个概念,将以前一堆松散的概念和文件组织到一起了,这才是关键
React+redux+redux-saga中,每新增1个组件或者说新增1个页面,都要新增3个文件,sagas,reducers,action各自对应1个文件,编写的时候不停的切换,极其的麻烦,而且文件多了之后,文件的管理不是很方便
DVA正是解决这些问题的
首先,我想说一个问题,那就是……Dva这个名字……
咳,好吧,最初的最初我关注到这个框架,就是因为它的名字,然后就好奇的点进去了,然后就被它的优雅给吸引,再也不可自拔……
然后它的配置文件,叫roadhog
如果你是一名OWer,那么你已经想迫不及待的看下去了
为什么要用DVA呢?
以下是官方文档的说明:
易学易用:仅有 6 个 api,对 redux 用户尤其友好
elm 概念:通过 reducers, effects 和 subscriptions 组织 model
支持 mobile 和 react-native:跨平台
支持 HMR:目前基于 babel-plugin-dva-hmr 支持 components、routes 和 models 的 HMR
动态加载 Model 和路由:按需加载加快访问速度
插件机制:比如 dva-loading 可以自动处理 loading 状态,不用一遍遍地写 showLoading 和 hideLoading
完善的语法分析库 dva-ast:dva-cli 基于此实现了智能创建 model, router 等
支持 TypeScript:通过 d.ts
Let’s start!
首先奉上Dva官方文档地址,是发布在github上的:dva
首先是安装:
使用npm安装即可: npm install dva-cli@0.7 -g
需要注意的是:1.node版本必须在6.5以上 2.dva-cli必须版本在0.7.x(可以安装完dva-cli之后用dva -v查看一下版本号)
以上两点都是DVA官方的要求
然后使用new命令创建一个新的dva应用: dva new dva-demo
耐心等待创建完成
这是应用创建成功的提示
好的,现在我们来看创建好的工程~
可以先运行一下试试: npm run start
运行结果如图
url为:http://localhost:8000/#/?_k=gebc0m
嗯 一个奇怪的url
不过如果你对前端路由,或者说对react-router有所了解的话,就知道这是hashHistory
如果不习惯可以修改为browserHistory
在根目录下的index.js文件中
修改代码
再运行看看效果
url正常了
不过路由改成browserHistory的话,还需要后端代码的配合
现在我们来观察这个创建好的工程的目录
可以很明显的看到代码都放在src文件夹了
另外在public文件夹下放了一个index.html文件
我们打开它来看看
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Dva Demo</title> <link rel="stylesheet" href="/index.css" /></head><body><div id="root"></div><script src="/index.js"></script></body></html>
很明显,这是一个React典型应用的html模版文件,和用create-react-app脚手架创建的应用中生成的index.html内容差不多
我们几乎不对这个html进行代码改动,也不在里面加入html标签,css文件等,整个文件的重点只是body里的两行代码
<div id="root"></div>
这是确定了id的div标签,我们编写的React组件最后都是展示在这个div块里
<script src="/index.js"></script>
最后所有js文件都会打包到这个Js文件里统一加载
再来看js文件
整个程序的入口文件是根目录下的index.js文件
import dva from 'dva';import { browserHistory } from 'dva/router';import './index.css';// 1. Initializeconst app = dva({ history: browserHistory,});// 2. Plugins// app.use({});// 3. Modelapp.model(require('./models/example'));// 4. Routerapp.router(require('./router'));// 5. Startapp.start('#root');
dva-cli生成的文件给我们写的注释已经写的很清楚了
先初始化,再加载插件,再加载Model,再加载路由,最后启动程序
我们就根据这个过程来理清楚文件关系
先从第4步路由来分析
加载路由的语句为: app.router(require('./router'));
很明显能看出,加载的是同在根目录下的router.js文件
我们打开router.js文件
import React from 'react';import { Router, Route } from 'dva/router';import IndexPage from './routes/IndexPage';function RouterConfig({ history }) { return ( <Router history={history}> <Route path="/" component={IndexPage} /> </Router> );}export default RouterConfig;
可以很明显的看出,主体结构是配置react-router,拦截”/”,然后渲染IndexPage
根据import语句,找到routes目录下面的IndexPage.js
import React from 'react';import { connect } from 'dva';import styles from './IndexPage.css';function IndexPage() { return ( <div className={styles.normal}> <h1 className={styles.title}>Yay! Welcome to dva!</h1> <div className={styles.welcome} /> <ul className={styles.list}> <li>To get started, edit <code>src/index.js</code> and save to reload.</li> <li><a href="https://github.com/dvajs/dva-docs/blob/master/v1/en-us/getting-started.md">Getting Started</a></li> </ul> </div> );}IndexPage.propTypes = {};export default connect()(IndexPage);
显然,这是一个React组件,而且是Redux中所说的容器型的组件,因为在导出的时候通过connect这个高阶函数来装饰这个组件,以便能够从Redux状态树中获取数据
因为这是一个很简单的页面,并没有导入在Components目录下封装好的组件,如果是在实际开发,页面足够复杂的时候,会在Component中封装组件,然后在Routes目录下的中的组件导入,然后再导入路由文件中
components目录下的example.js
import React from 'react';const Example = () => { return ( <div> Example </div> );};Example.propTypes = {};export default Example;
只是1个示例文件,没有使用它,它本身也没什么意义
我们再回到根目录下的index.js中,第4步路由部分加载的文件我们已经回溯到底了,我们来看第3步model
app.model(require('./models/example'));
可以看出,加载的是models目录下的example.js文件
打开查看其代码
export default { namespace: 'example', state: {}, subscriptions: { setup({ dispatch, history }) { // eslint-disable-line }, }, effects: { *fetch({ payload }, { call, put }) { // eslint-disable-line yield put({ type: 'save' }); }, }, reducers: { save(state, action) { return { ...state, ...action.payload }; }, },};
model这个概念,是dva的核心,可以看到上面代码中主要分为几个字段:namespace,state,subscriptions,effects,reducers
这几个字段,官方文档中给出的说明是这样的:
namespace - 对应 reducer 在 combine 到 rootReducer 时的 key 值
state - 对应 reducer 的 initialState
subscription - elm@0.17 的新概念,在 dom ready 后执行
effects - 对应 saga,并简化了使用
reducers- 还是对应原来的reducer,概念没有变化
熟悉react,redux, redux-saga 这一套应用架构的,无缝切换
可以看到,关于redux中action,reducer的那一堆,都集中在model里面了,编写代码再也不用切换过去切换过来,而且在一个文件中,组织代码非常方便,再也不用code everywhere
services目录下的文件是为models目录下的文件服务的
更多的,可以去看官方给出的一个CURD用户管理的demo
12 步 30 分钟,完成用户管理的 CURD 应用
- 基于react+redux的轻量级框架dva初使用及应用逻辑分析
- 基于redux的前端框架dva入门教程
- 基于react+redux+webpack的前端框架
- 基于 Redux 的 React Native 应用架构
- react-navigation使用及dva初探一
- react-navigation使用及dva初探二
- react-navigation及dva使用(三)
- 使用Redux管理你的React应用
- 使用Redux管理你的React应用
- 使用Redux管理你的React应用
- 基于react、redux的todoLists
- 基于React-Native及Redux的Immutable.js引入
- 基于React-Native及Redux的Immutable.js引入
- 基于react、react-redux的加减计数器
- 基于React,dva脚手架的知乎日报
- react的dva框架,service不能获取数据的问题
- 使用JWT验证在我们的React&Redux应用中
- React-Native中使用redux的原理分析
- 中缀表达式与前缀、后缀表达式的转换
- 表达式语言
- FileWritter写入文件
- Codeforces Round #439 E. The Untended Antiquity (树状数组+随机化)
- MODBUS-RTU数据帧格式、报文实例
- 基于react+redux的轻量级框架dva初使用及应用逻辑分析
- office2016(包括其他版本)办公软件破解方式
- Linux 基本操作和相关命令
- koa2 入门及express应用迁移到koa2实例
- python里使用正则表达式的重复模式
- 用node从零开始去写一个简单的爬虫
- java写入文件的几种方法
- HTML CSS 定位 position
- 批量图片灰度化小程序