DvaJS学习(dva = React-Router + Redux + Redux-saga)

我们来介绍一下,dva出自于暴雪出品的一款游戏《守望先锋》,援引官方的角色介绍:

D.Va拥有一部强大的机甲,它具有两台全自动的近距离聚变机炮、可以使机甲飞跃敌人或障碍物的推进器、还有可以抵御来自正面的远程攻击的防御矩阵。
在这里插入图片描述

然后呢,蚂蚁金服的一位架构师sorrycc很迷这位美女,正巧刚开发了一款前端框架没有名字,作为一个向女神献礼的项目,dva框架就此诞生。

我们先看看React 没有解决的问题

React 没有解决的问题

React 本身只是一个 DOM 的抽象层,使用组件构建虚拟 DOM。

如果开发大应用,还需要解决一个问题。

  • 通信:组件之间如何通信?
  • 数据流:数据如何和视图串联起来?路由和数据如何绑定?如何编写异步逻辑?等等

通信问题

组件会发生三种通信。

  • 向子组件发消息
  • 向父组件发消息
  • 向其他组件发消息

React 只提供了一种通信手段:传参。对于大应用,很不方便。

数据流问题

目前流行的数据流方案有:

  • Flux,单向数据流方案,以 Redux 为代表
  • Reactive,响应式数据流方案,以 Mobx 为代表
  • 其他,比如 rxjs 等

到底哪一种架构最合适 React ?

目前最流行的数据流方案:

  • 路由: React-Router
  • 架构: Redux
  • 异步操作: Redux-saga

缺点:要引入多个库,项目结构复杂。

何为 dva

dva 是体验技术部开发的 React 应用框架,将上面三个 React 工具库包装在一起,简化了 API,让开发 React 应用更加方便和快捷。

dva = React-Router + Redux + Redux-saga

dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了react-router 和 fetch。

实际上,dva只是基于现有开源框架的一层轻量封装,并没有引入任何新概念:

  • React:管理View
  • react-router:管理路由
  • Redux:管理Model
  • redux-saga:管理异步调用(副作用)

dva 应用的最简结构

import dva from 'dva';
const App = () => <div>Hello dva</div>;

// 创建应用
const app = dva();
// 注册视图
app.router(() => <App />);
// 启动应用
app.start('#root');

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');

Dva 概念

数据流图

数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 通过server交互获取数据然后流向 Reducers 最终改变 State,同样state通过connect将model、状态数据与组件相连

总的数据流图:
在这里插入图片描述

数据流图1:最简单

在这里插入图片描述

  • State:一个对象,保存整个应用状态
  • View:React 组件构成的视图层
  • Action:一个对象,描述事件
  • connect 方法:一个函数,绑定 State 到 View
  • dispatch 方法:一个函数,发送 Action 到 State
数据流图2:使用中间件

在这里插入图片描述

数据流图3:使用中间件 副作用

在这里插入图片描述

View

View 就是 React 组件构成的 UI 层,从 State 取数据后,渲染成 HTML 代码。只要 State 有变化,View 就会自动更新。

Models

  • namespace: 当前 Model 的名称。整个应用的 State,由多个小的 Model 的 State 以 namespace 为 key 合成
  • state: 该 Model 当前的状态。数据保存在这里,直接决定了视图层的输出
  • reducers: Action 处理器,处理同步动作,用来算出最新的 State
  • effects:Action 处理器,处理异步动作
namespace

model 的命名空间,同时也是他在全局 state 上的属性,只能用字符串,不支持通过 . 的方式创建多层命名空间。

当前 Model 的名称。整个应用的 State,由多个小的 Model 的 State 以 namespace 为 key 合成。

在组件里面,通过connect将这个key引入到相应的model中。
在这里插入图片描述
在这里插入图片描述

State

初始值,优先级低于传给 dva() 的 opts.initialState。

State 是储存数据的地方,收到 Action 以后,会更新数据。

State 表示 Model 的状态数据,通常表现为一个 javascript 对象(当然它可以是任何值);

const app = dva({
   
  initialState: {
    count: 1 },
});
app.model({
   
  namespace: 'count',
  state: 0,
});

此时,在 app.start() 后 state.count 为 1 。

Reducer

Action 处理器,处理同步动作,用来算出最新的 State

type Reducer<S, A> = (state: S, action: A) => S

以 key/value 格式定义 reducer。用于处理同步操作,唯一可以修改 state 的地方。由 action 触发。

格式为 (state, action) => newState 或 [(state, action) => newState, enhancer]

 reducers: {
   
    save(state, action) {
   
      return {
    ...state, ...action.payload };
    },
  },

📌Action

  • Action 是用来描述 UI 层事件的一个 javascript 对象
  • 它是改变 State 的唯一途径。
  • 通过 dispatch 函数调用一个 action
  • 必须包含type字段
{
   
  type: 'click-submit-button',
  payload: this.form.data
}
Effect

Action 处理器,处理异步动作,不直接修改 state。Effect 指的是副作用。根据函数式编程,计算以外的操作都属于 Effect,典型的就是 I/O 操作、数据库读写。副作用是因为它使函数变得不纯,同样的输入不一定获得同样的输出。

  effects: {
   
    *fetch({
    payload }, {
    call, put }) {
     // eslint-disable-line
      yield put({
    type: 'sav
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值