【React】Dva.js上手入门教程

Dva.js 上手入门教程(基于 React)

一、Dva.js 简介

Dva.js 是一个基于 React 和 Redux 的轻量级前端框架,封装了 Redux、Redux-saga 和 React-router,简化了状态管理和数据流的处理。它通过约定优于配置的方式,让开发者可以更专注于业务逻辑的实现。


二、安装与初始化项目

1. 安装 Node.js 和 npm

确保你的开发环境已经安装了 Node.js(建议使用 LTS 版本)和 npm(Node.js 包管理器)。

2. 全局安装 Dva-cli

Dva 提供了命令行工具 dva-cli,用于快速创建和管理 Dva 项目。

npm install -g dva-cli

3. 创建新项目

使用 dva new 命令创建一个新的 Dva 项目。

dva new my-dva-app
cd my-dva-app

4. 启动项目

进入项目目录后,运行以下命令启动开发服务器:

npm start

项目启动后,默认会在浏览器中打开 http://localhost:8000,显示 Dva 的默认页面。


三、项目结构解析

Dva 项目的默认目录结构如下:

my-dva-app/
├── src/
│   ├── components/       # 公共组件
│   ├── models/           # 数据模型(核心)
│   ├── routes/           # 页面组件
│   ├── services/         # API 服务
│   ├── utils/            # 工具函数
│   ├── index.js          # 项目入口文件
│   └── router.js         # 路由配置
├── .editorconfig          # 编辑器配置
├── .eslintrc             # ESLint 配置
├── .roadhogrc            # 打包配置
└── package.json          # 项目依赖

四、核心概念与代码示例

1. Model(数据模型)

Model 是 Dva 的核心概念,用于管理应用的状态和逻辑。每个 Model 包含以下部分:

  • namespace: 命名空间,用于隔离不同 Model 的状态。
  • state: 初始状态。
  • reducers: 同步操作,用于更新状态。
  • effects: 异步操作,通常用于调用 API。
  • subscriptions: 订阅,用于监听外部事件(如路由变化)。
示例:创建一个计数器 Model

src/models/counter.js 中定义:

export default {
  namespace: 'counter',  // 命名空间
  state: {               // 初始状态
    count: 0,
  },
  reducers: {           // 同步操作
    add(state) {        // 更新状态,必须返回新对象
      return { ...state, count: state.count + 1 };
    },
    minus(state) {      // 减少计数
      return { ...state, count: state.count - 1 };
    },
  },
  effects: {            // 异步操作
    *addAsync({ payload }, { call, put }) { // Generator 函数
      yield call(delay, 1000); // 模拟异步操作(延迟 1 秒)
      yield put({ type: 'add' }); // 触发同步操作
    },
  },
  subscriptions: {      // 订阅
    setup({ dispatch, history }) {
      return history.listen(({ pathname }) => {
        if (pathname === '/') {
          dispatch({ type: 'init' }); // 初始化操作
        }
      });
    },
  },
};

// 辅助函数:延迟
function delay(timeout) {
  return new Promise(resolve => setTimeout(resolve, timeout));
}

2. 组件(Component)与连接(Connect)

在 React 组件中,通过 dvaconnect 方法将 Model 的状态和操作绑定到组件的 props 上。

示例:计数器组件

src/routes/CounterPage.js 中定义:

import React from 'react';
import { connect } from 'dva';
import { Button } from 'antd'; // 使用 Ant Design 组件

function CounterPage({ count, dispatch }) {
  return (
    <div style={{ padding: '20px' }}>
      <h2>当前计数: {count}</h2>
      <Button 
        type="primary" 
        onClick={() => dispatch({ type: 'counter/add' })}
        style={{ marginRight: '10px' }}
      >
        增加
      </Button>
      <Button 
        onClick={() => dispatch({ type: 'counter/minus' })}
        style={{ marginRight: '10px' }}
      >
        减少
      </Button>
      <Button 
        type="dashed" 
        onClick={() => dispatch({ type: 'counter/addAsync' })}
      >
        异步增加(1秒后)
      </Button>
    </div>
  );
}

// 将 Model 的状态和操作绑定到组件的 props
export default connect(({ counter }) => ({
  count: counter.count, // 从 counter Model 的 state 中获取 count
}))(CounterPage);

3. 路由配置

src/router.js 中配置路由:

import React from 'react';
import { Router, Route, Switch } from 'dva/router';
import CounterPage from './routes/CounterPage';

function RouterConfig({ history }) {
  return (
    <Router history={history}>
      <Switch>
        <Route path="/" exact component={CounterPage} />
      </Switch>
    </Router>
  );
}

export default RouterConfig;

五、实际业务场景应用

1. 调用 API(异步操作)

在实际项目中,通常需要调用后端 API 获取数据。Dva 的 effects 用于处理异步操作。

示例:获取用户列表
  1. 定义 Service
    src/services/user.js 中定义 API 调用:

    import request from '../utils/request'; // 封装好的请求工具
    
    export async function fetchUsers() {
      return request('/api/users'); // 返回 Promise
    }
    
  2. 定义 Model
    src/models/user.js 中定义:

    import { fetchUsers } from '../services/user';
    
    export default {
      namespace: 'user',
      state: {
        list: [],
        loading: false,
      },
      effects: {
        *fetch({ payload }, { call, put }) {
          yield put({ type: 'showLoading' }); // 显示加载状态
          try {
            const response = yield call(fetchUsers, payload);
            yield put({ type: 'save', payload: response.data }); // 保存数据
          } catch (error) {
            console.error('获取用户列表失败:', error);
          } finally {
            yield put({ type: 'hideLoading' }); // 隐藏加载状态
          }
        },
      },
      reducers: {
        save(state, { payload }) {
          return { ...state, list: payload };
        },
        showLoading(state) {
          return { ...state, loading: true };
        },
        hideLoading(state) {
          return { ...state, loading: false };
        },
      },
    };
    
  3. 定义组件
    src/routes/UserPage.js 中定义:

    import React from 'react';
    import { connect } from 'dva';
    import { Table, Spin } from 'antd';
    
    function UserPage({ list, loading, dispatch }) {
      React.useEffect(() => {
        dispatch({ type: 'user/fetch' }); // 组件挂载时获取数据
      }, []);
    
      const columns = [
        { title: 'ID', dataIndex: 'id', key: 'id' },
        { title: '姓名', dataIndex: 'name', key: 'name' },
        { title: '邮箱', dataIndex: 'email', key: 'email' },
      ];
    
      return (
        <div style={{ padding: '20px' }}>
          <h2>用户列表</h2>
          <Spin spinning={loading}>
            <Table 
              dataSource={list} 
              columns={columns} 
              rowKey="id" 
            />
          </Spin>
        </div>
      );
    }
    
    export default connect(({ user }) => ({
      list: user.list,
      loading: user.loading,
    }))(UserPage);
    

六、总结

  1. Dva.js 核心概念
    • Model:管理状态和逻辑。
    • Reducers:同步操作。
    • Effects:异步操作。
    • Subscriptions:订阅外部事件。
  2. 开发流程
    • 定义 Model。
    • 编写组件并通过 connect 绑定 Model。
    • 配置路由。
  3. 实际业务
    • 使用 effects 调用 API。
    • 使用 reducers 更新状态。
    • 使用 Ant Design 等 UI 库快速构建界面。

通过以上步骤,你可以快速上手 Dva.js 并开发基于 React 的中大型前端应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值