Dva.js 快速上手文档

1. Dva.js 概念

Dva.js 是基于 Reduxredux-saga 的数据流框架,它提供了以下几个核心概念:

  • Model(模型): 用于描述数据、状态和副作用的管理。

  • State(状态): 应用中的数据,存储在每个 Model 中。

  • Reducer(同步处理): 用来同步更新 Model 中的 state。

  • Effect(副作用处理): 用于处理异步操作,通常与 redux-saga 配合使用。

  • Dispatch(派发): 用于触发 Action,更新状态或执行副作用。

  • Connect(连接): 将组件与 Dva 的状态(State)和方法(Dispatch)进行绑定。

1.1. 基本架构

Dva.js 提供了以下三大核心组成部分:

  • Model:用于定义应用状态、同步操作(reducer)和异步操作(effect)。

  • Store:类似于 Redux 中的 store,存储了应用的状态和处理函数。

  • Router:使用 React Router 进行页面导航。

2. 安装 Dva.js

首先,你需要有一个 React 项目。如果没有,请使用 create-react-app 创建一个新项目。

npx create-react-app my-dva-app
cd my-dva-app
npm install dva

3. Dva.js API

Dva.js 提供了一些常用的 API 来初始化应用、定义模型、注册路由等。

3.1. 初始化应用 (dva())

通过 dva() 函数来初始化一个 Dva 应用,它是应用的入口。

import dva from 'dva';
 
// 初始化应用
const app = dva();

3.2. 定义 Model

Dva 中的 Model 用于管理数据和副作用。每个 Model 包含以下几个部分:

  • namespace: 模型的命名空间(全局唯一)。

  • state: 模型的初始状态。

  • reducers: 用来更新状态的同步方法。

  • effects: 用来处理副作用(如异步请求)的函数。

3.2.1. 示例:定义一个简单的 Model

// 定义一个 Model
app.model({
  namespace: 'counter',
  state: {
    count: 0
  },
  reducers: {
    // 更新 state
    add(state) {
      return { ...state, count: state.count + 1 };
    },
    reduce(state) {
      return { ...state, count: state.count - 1 };
    },
  },
  effects: {
    // 异步操作
    *asyncAdd(action, { put }) {
      yield new Promise(resolve => setTimeout(resolve, 1000)); // 模拟延时
      yield put({ type: 'add' });
    }
  }
});

3.3. 路由配置 (app.router)

在 Dva.js 中,你需要使用 app.router() 来定义应用的路由,通常结合 React Router 使用。

import React from 'react';
import { Router, Route, Switch } from 'dva/router';
 
app.router(({ history }) => (
  <Router history={history}>
    <Switch>
      <Route path="/" exact component={Home} />
      <Route path="/about" component={About} />
    </Switch>
  </Router>
));

3.4. 启动应用 (app.start)

在所有的模型定义和路由配置完成后,使用 app.start() 启动应用。

app.start('#root'); // 挂载到页面中的 #root 元素

4. Dva.js 语法与用法

4.1. model 定义

4.1.1. namespace(命名空间)

每个 Model 必须有一个唯一的命名空间,通常与模型功能相关,如 counteruser 等。

4.1.2. state(状态)

state 用于存储模型的数据。例如,计数器的 count

4.1.3. reducers(同步操作)

reducers 用于同步更新 state,通过 type 来指定哪个 reducer 进行处理。

reducers: {
  add(state) {
    return { ...state, count: state.count + 1 };
  },
  reduce(state) {
    return { ...state, count: state.count - 1 };
  }
}

4.1.4. effects(副作用)

effects 用于处理异步操作,可以通过 call 来调用异步操作,put 来派发 Action 更新 state

effects: {
  *asyncAdd(action, { call, put }) {
    yield call(delay, 1000); // 模拟延时
    yield put({ type: 'add' });
  }
}

4.1.5. subscriptions(订阅)

subscriptions 用于监听路由变化或其他事件,并做出反应。通常用于页面加载时获取数据。

subscriptions: {
  setup({ dispatch, history }) {
    return history.listen(({ pathname }) => {
      if (pathname === '/') {
        dispatch({ type: 'fetchData' });
      }
    });
  }
}

4.2. connect(连接)

通过 connect 将 Redux store 中的 statedispatch 映射到组件的 props 中。

import { connect } from 'dva';
 
const Counter = ({ count, dispatch }) => (
  <div>
    <h1>Count: {count}</h1>
    <button onClick={() => dispatch({ type: 'counter/add' })}>+</button>
    <button onClick={() => dispatch({ type: 'counter/reduce' })}>-</button>
  </div>
);
 
export default connect(({ counter }) => ({
  count: counter.count
}))(Counter);

4.3. Effects 与 redux-saga

Dva.js 内置了 redux-saga,用于处理副作用(如异步请求、定时器等)。effects 中的每个函数都是一个 Generator 函数。

effects: {
  *fetchData(action, { call, put }) {
    const data = yield call(fetchDataFromAPI); // 异步请求
    yield put({ type: 'saveData', payload: data }); // 更新 state
  }
}

4.4. 生命周期

Dva.js 有多个生命周期钩子,供开发者处理不同的事件。

  • onEffect:在每次调用 effects 前触发。

  • onReducer:在每次调用 reducer 前触发。

4.5. 状态的派发和监听

Dva.js 使用 dispatch 来触发 action,dispatch 可以通过 type 指定哪个 action 被触发。

// 同步更新状态
dispatch({ type: 'counter/add' });
 
// 异步操作
dispatch({ type: 'counter/asyncAdd' });

你可以通过 connect 来获取应用的状态,并在组件中使用这些状态。

5. 示例:完整的 Dva.js 应用

import React from 'react';
import dva from 'dva';
import { connect } from 'dva';
 
// 初始化应用
const app = dva();
 
// 定义 Model
app.model({
  namespace: 'counter',
  state: { count: 0 },
  reducers: {
    add(state) {
      return { ...state, count: state.count + 1 };
    },
    reduce(state) {
      return { ...state, count: state.count - 1 };
    },
  },
  effects: {
    *asyncAdd(action, { call, put }) {
      yield new Promise(resolve => setTimeout(resolve, 1000)); // 模拟异步操作
      yield put({ type: 'add' });
    },
  },
});
 
// 定义组件
const Counter = ({ count, dispatch }) => (
  <div>
    <h1>Count: {count}</h1>
    <button onClick={() => dispatch({ type: 'counter/add' })}>+</button>
    <button onClick={() => dispatch({ type: 'counter/reduce' })}>-</button>
    <button onClick={() => dispatch({ type: 'counter/asyncAdd' })}>Async +</button>
  </div>
);
 
// 使用 connect 连接状态
const ConnectedCounter = connect(({ counter }) => ({
  count: counter.count,
}))(Counter);
 
// 配置路由
app.router(() => <ConnectedCounter />);
 
// 启动应用
app.start('#root');

总结

Dva.js 是一个强大的框架,基于 Reduxredux-saga 实现了简洁且高效的状态管理方案。它通过 Model 来组织

状态、异步操作和副作用,使得复杂的应用逻辑更容易理解和维护。

  • Model 定义了应用的状态和操作。

  • Effect 用于处理异步操作和副作用。

  • Reducer 用于同步更新状态。

  • Dispatch 用于触发操作和状态变化。

希望这份文档能帮助你更好地理解和使用 Dva.js!如果有任何问题,随时联系我。