React应用框架DvaJs入门
1 什么是Dva?
dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。
2 特性
- 易学易用,仅有 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
3 Dva中常见的概念
4 数据流向
数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch
发起一个 action,如果是同步行为会直接通过 Reducers
改变 State
,如果是异步行为(副作用)会先触发 Effects
然后流向 Reducers
最终改变 State
,所以在 dva 中,数据流向非常清晰简明,并且思路基本跟开源社区保持一致(也是来自于开源社区)。
5 Models
State
type State = any
State 表示 Model 的状态数据,通常表现为一个 javascript 对象(当然它可以是任何值);操作的时候每次都要当作不可变数据(immutable data)来对待,保证每次都是全新对象,没有引用关系,这样才能保证 State 的独立性,便于测试和追踪变化。
在 dva 中你可以通过 dva 的实例属性 _store
看到顶部的 state 数据,但是通常你很少会用到:
const app = dva();
console.log(app._store); // 顶部的 state 数据
Action
type AsyncAction = any
Action 是一个普通 javascript 对象,它是改变 State 的唯一途径。无论是从 UI 事件、网络回调,还是 WebSocket 等数据源所获得的数据,最终都会通过 dispatch 函数调用一个 action,从而改变对应的数据。action 必须带有 type
属性指明具体的行为,其它字段可以自定义,如果要发起一个 action 需要使用 dispatch
函数;需要注意的是 dispatch
是在组件 connect Models以后,通过 props 传入的。
dispatch({type: 'add',
});
dispatch 函数
type dispatch = (a: Action) => Action
dispatching function 是一个用于触发 action 的函数,action 是改变 State 的唯一途径,但是它只描述了一个行为,而 dipatch 可以看作是触发这个行为的方式,而 Reducer 则是描述如何改变数据的。
在 dva 中,connect Model 的组件通过 props 可以访问到 dispatch,可以调用 Model 中的 Reducer 或者 Effects,常见的形式如:
dispatch({type: 'user/add', // 如果在 model 外调用,需要添加 namespacepayload: {}, // 需要传递的信息
});
Reducer
type Reducer<S, A> = (state: S, action: A) => S
Reducer(也称为 reducing function)函数接受两个参数:之前已经累积运算的结果和当前要被累积的值,返回的是一个新的累积结果。该函数把一个集合归并成一个单值。
Reducer 的概念来自于是函数式编程,很多语言中都有 reduce API。如在 javascript 中:
[{x:1},{y:2},{z:3}].reduce(function(prev, next){return Object.assign(prev, next);
})
//return {x:1, y:2, z:3}
在 dva 中,reducers 聚合积累的结果是当前 model 的 state 对象。通过 actions 中传入的值,与当前 reducers 中的值进行运算获得新的值(也就是新的 state)。需要注意的是 Reducer 必须是纯函数,所以同样的输入必然得到同样的输出,它们不应该产生任何副作用。并且,每一次的计算都应该使用immutable data,这种特性简单理解就是每次操作都是返回一个全新的数据(独立,纯净),所以热重载和时间旅行这些功能才能够使用。
Effect
Effect 被称为副作用,在我们的应用中,最常见的就是异步操作。它来自于函数编程的概念,之所以叫副作用是因为它使得我们的函数变得不纯,同样的输入不一定获得同样的输出。
dva 为了控制副作用的操作,底层引入了redux-sagas做异步流程控制,由于采用了generator的相关概念,所以将异步转成同步写法,从而将effects转为纯函数。至于为什么我们这么纠结于 纯函数,如果你想了解更多可以阅读Mostly adequate guide to FP,或者它的中文译本JS函数式编程指南。
Subscription
Subscriptions 是一种从 源 获取数据的方法,它来自于 elm。
Subscription 语义是订阅,用于订阅一个数据源,然后根据条件 dispatch 需要的 action。数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。
import key from 'keymaster';
...
app.model({namespace: 'count',subscriptions: {keyEvent({dispatch}) {key('⌘+up, ctrl+up', () => { dispatch({type:'add'}) });},}
});
6 Router
这里的路由通常指的是前端路由,由于我们的应用现在通常是单页应用,所以需要前端代码来控制路由逻辑,通过浏览器提供的 History API 可以监听浏览器url的变化,从而控制路由相关操作。
dva 实例提供了 router 方法来控制路由,使用的是react-router。
import { Router, Route } from 'dva/router';
app.router(({history}) =><Router history={history}><Route path="/" component={HomePage} /></Router>
);
7 Route Components
在组件设计方法中,我们提到过 Container Components,在 dva 中我们通常将其约束为 Route Components,因为在 dva 中我们通常以页面维度来设计 Container Components。
所以在 dva 中,通常需要 connect Model的组件都是 Route Components,组织在/routes/
目录下,而/components/
目录下则是纯组件(Presentational Components)。
8 入门课
React 没有解决的问题
React 本身只是一个 DOM 的抽象层,使用组件构建虚拟 DOM。
如果开发大应用,还需要解决一个问题。
- 通信:组件之间如何通信?
- 数据流:数据如何和视图串联起来?路由和数据如何绑定?如何编写异步逻辑?等等
通信问题
组件会发生三种通信。
- 向子组件发消息
- 向父组件发消息
- 向其他组件发消息
React 只提供了一种通信手段:传参。对于大应用,很不方便。
组件通信的例子
步骤1
class Son extends React.Component {render() {return <input/>;}
}class Father extends React.Component {render() {return <div><Son/><p>这里显示 Son 组件的内容</p></div>;}
}ReactDOM.render(<Father/>, mountNode);
看这个例子,想一想父组件如何拿到子组件的值。
步骤2
class Son extends React.Component {render() {return <input onChange={this.props.onChange}/>;}
}class Father extends React.Component {constructor() {super();this.state = {son: ""}}changeHandler(e) {this.setState({son: e.target.value});}render() {return <div><Son onChange={this.changeHandler.bind(this)}/><p>这里显示 Son 组件的内容:{this.state.son}</p></div>;}
}ReactDOM.render(<Father/>, mountNode);
看下这个例子,看懂源码,理解子组件如何通过父组件传入的函数,将自己的值再传回父组件。
数据流问题
目前流行的数据流方案有:
- Flux,单向数据流方案,以 Redux 为代表
- Reactive,响应式数据流方案,以 Mobx 为代表
- 其他,比如 rxjs 等
到底哪一种架构最合适 React ?
目前最流行的数据流方案
截止 2017.1,最流行的社区 React 应用架构方案如下。
- 路由: React-Router
- 架构: Redux
- 异步操作: Redux-saga
缺点:要引入多个库,项目结构复杂。
dva 是什么
dva 是体验技术部开发的 React 应用框架,将上面三个 React 工具库包装在一起,简化了 API,让开发 React 应用更加方便和快捷。
dva = React-Router + Redux + Redux-saga
dva 应用的最简结构
import dva from 'dva';
const App = () => <div>Hello dva</div>;// 创建应用
const app = dva();
// 注册视图
app.router(() => <App />);
// 启动应用
app.start('#root');
数据流图
核心概念
- State:一个对象,保存整个应用状态
- View:React 组件构成的视图层
- Action:一个对象,描述事件
- connect 方法:一个函数,绑定 State 到 View
- dispatch 方法:一个函数,发送 Action 到 State
State 和 View
State 是储存数据的地方,收到 Action 以后,会更新数据。
View 就是 React 组件构成的 UI 层,从 State 取数据后,渲染成 HTML 代码。只要 State 有变化,View 就会自动更新。
Action
Action 是用来描述 UI 层事件的一个对象。
{type: 'click-submit-button',payload: this.form.data
}
connect 方法
connect 是一个函数,绑定 State 到 View。
import { connect } from 'dva';function mapStateToProps(state) {return { todos: state.todos };
}
connect(mapStateToProps)(App);
connect 方法返回的也是一个 React 组件,通常称为容器组件。因为它是原始 UI 组件的容器,即在外面包了一层 State。
connect 方法传入的第一个参数是 mapStateToProps 函数,mapStateToProps 函数会返回一个对象,用于建立 State 到 Props 的映射关系。
dispatch 方法
dispatch 是一个函数方法,用来将 Action 发送给 State。
dispatch({type: 'click-submit-button',payload: this.form.data
})
dispatch 方法从哪里来?被 connect 的 Component 会自动在 props 中拥有 dispatch 方法。
connect 的数据从哪里来?
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' });},},
});// 注册视图
app.router(() => <ConnectedApp />);// 启动应用
app.start('#root');
数据流图 1
数据流图 2
app.model
dva 提供 app.model 这个对象,所有的应用逻辑都定义在它上面。
const app = dva();// 新增这一行
app.model({ /**/ });app.router(() => <App />);
app.start('#root');
Model 对象的例子
{namespace: 'count',state: 0,reducers: {add(state) { return state + 1 },},effects: {*addAfter1Second(action, { call, put }) {yield call(delay, 1000);yield put({ type: 'add' });},},
}
Model 对象的属性
- namespace: 当前 Model 的名称。整个应用的 State,由多个小的 Model 的 State 以 namespace 为 key 合成
- state: 该 Model 当前的状态。数据保存在这里,直接决定了视图层的输出
- reducers: Action 处理器,处理同步动作,用来算出最新的 State
- effects:Action 处理器,处理异步动作
Reducer
Reducer 是 Action 处理器,用来处理同步操作,可以看做是 state 的计算器。它的作用是根据 Action,从上一个 State 算出当前 State。
一些例子:
// count +1
function add(state) { return state + 1; }// 往 [] 里添加一个新 todo
function addTodo(state, action) { return [...state, action.payload]; }// 往 { todos: [], loading: true } 里添加一个新 todo,并标记 loading 为 false
function addTodo(state, action) {return {...state,todos: state.todos.concat(action.payload),loading: false};
}
Effect
Action 处理器,处理异步动作,基于 Redux-saga 实现。Effect 指的是副作用。根据函数式编程,计算以外的操作都属于 Effect,典型的就是 I/O 操作、数据库读写。
function *addAfter1Second(action, { put, call }) {yield call(delay, 1000);yield put({ type: 'add' });
}
Generator 函数
Effect 是一个 Generator 函数,内部使用 yield 关键字,标识每一步的操作(不管是异步或同步)。
call 和 put
dva 提供多个 effect 函数内部的处理函数,比较常用的是 call
和 put
。
- call:执行异步函数
- put:发出一个 Action,类似于 dispatch
原文链接-DvaJs官网:https://dvajs.com/guide/
写博客是为了记住自己容易忘记的东西,另外也是对自己工作的总结,希望尽自己的努力,做到更好,大家一起努力进步!
如果有什么问题,欢迎大家评论,一起探讨,代码如有问题,欢迎各位大神指正!
给自己的梦想添加一双翅膀,让它可以在天空中自由自在的飞翔!
React应用框架DvaJs入门相关推荐
- React 应用框架:DvaJS
最近在学习react相关的东西,记录一下react 开发中,组件通信和数据流的应用框架 dva: 一.dva是什么?要解决的问题? React 本身只是一个 DOM 的抽象层,使用组件构建虚拟 DOM ...
- react ui框架_顶级React组件库推荐
作者丨Max Rozen 译者丨王强 策划丨小智 转发链接:https://mp.weixin.qq.com/s/-vRr8Qd8DCNiza09eZjmbQ 本文最初发布于 maxrozen.com ...
- React学习笔记:入门案例
React学习笔记:入门案例 React 起源于 Facebook 内部项目,因为市场上所有 JavaScript MVC 框架都不令人满意,公司就决定自己写一套,用来架设 Instagram 的网站 ...
- 必须收藏!这13个优秀React JS框架,没用过就很离谱!
如果你正在使用React.js或React Native创建用户界面,可以试一试本文推荐的这些框架. React.js和React Native是流行的用户界面(UI)开发平台,且都是开源技术.在 ...
- 视频教程-React 全家桶从入门到实战到源码-其他
React 全家桶从入门到实战到源码 上市公司前端开发工程师,专注于 React 技术栈,对 React 全家桶从 react-router 路由到 Redux 状态管理工具再到 webpack 打包 ...
- 视频教程-新React+VUE前端教程入门到精通-Vue
新React+VUE前端教程入门到精通 10年以上开发经验,曾经是八维教育实训主任,千峰教育高级HTML5前端讲师,尚品中国创始人.现任程序思维创始人.曾和大厂.国企等大型企业合作开发项目.百余客户, ...
- 视频教程-React.js框架技术-Java
React.js框架技术 软通动力教育集团简称软通大学,依托软通动力在技术服务领域的多方位解决方案能力,采用先进的教学理念和模式,直通高校和城市,开展干部培养,文化落地,初级资源培训,培训需求对接,专 ...
- DvaJS 入门, 快速上手Dva
为什么要使用Dva? React 没有解决的问题 React 本身只是一个 DOM 的抽象层,使用组件构建虚拟 DOM. 如果开发大应用,还需要解决一个问题. 通信:组件之间如何通信? 数据流:数据如 ...
- 从Preact了解一个类React的框架是怎么实现的(一): 元素创建
首先欢迎大家关注我的掘金账号和Github博客,也算是对我的一点鼓励,毕竟写东西没法获得变现,能坚持下去也是靠的是自己的热情和大家的鼓励. 之前分享过几篇关于React的文章: React技术内幕: ...
最新文章
- Linux下使用diff和patch制作及打补丁(已经实践可行!)
- Azure Neural TTS能让AI语音自然逼真到什么程度?
- 整理Java基础知识--输出格式知识
- 你应该知道的grep命令
- 简述用决策表设计测试用例的步骤_决策表快速入门
- 服务器标记“asp:ScriptManager”不明确。
- linux stdin STDIN_FILENO 区别
- python 透视变换补边
- 数据挖掘十大经典算法之——KNN 算法
- Keepalived - Keepalived 实现 tomcat双机热备
- python:数据操作小技巧
- ubuntu 的QT4的qmake失败的处理方法
- 【复杂系统迁移 .NET Core平台系列】之迁移项目工程
- 第一章 概率论的基本概念
- python打印九九加法表_Python小脚本
- python基础(2)
- Win10 UWP系列:关于错误 0x80073CF9及一个小bug的解决
- 变量存储list python_Python变量类型(八)
- mysql 搜索_MySQL模糊搜索的几种姿势
- 水晶报表基础入门——6.交叉报表设计技术