当前位置: 首页 > news >正文

React封装框架dvajs(状态管理+异步操作+数据订阅等)

目录

DvaJS 简介

一、核心特性

1.1 简化 Redux 开发

1.2 集成 Redux-Saga

1.3 内置 React-Router

1.4 Model 驱动开发

1.5 插件机制

二、基本使用

2.1 安装及创建

2.2 目录结构

2.3 路由使用

2.4 状态管理 models_reducer(同步)(以计数器为例)

2.4.1 创建model

2.4.2 引入model

2.4.3 使用connect进行同步操作

2.5 状态管理 models_effects(异步)

2.5.1 修改model

2.5.2 异步操作

2.6 订阅监听(subscriptions)(以检查登录状态为例)

2.7 模拟数据(mock)

2.7.1 创建mock

2.7.2 注册mock

2.7.3 获取数据


 

DvaJS 简介

DvaJS 是一个基于 ReactRedux 的轻量级前端框架,由支付宝团队开发并开源。它整合了 Redux、Redux-Saga、React-Router 等库,并提供了更简洁的开发模式,适用于构建复杂的中后台管理系统。

一、核心特性

1.1 简化 Redux 开发

  • 内置 Redux 状态管理,但通过 model 概念简化了 actionreducereffect(异步逻辑)的定义。

  • 不再需要手动编写 action typesreducerswitch-case

1.2 集成 Redux-Saga

  • 使用 Saga 处理异步逻辑(如 API 请求),支持 async/await 风格。

  • 提供 effects 语法糖,简化 putcalltake 等 Saga 操作。

1.3 内置 React-Router

  • 支持动态路由配置,简化路由管理。

1.4 Model 驱动开发

  • 应用状态和逻辑按 model 组织,每个 model 包含:

    • namespace(命名空间,类似模块名)

    • state(初始状态)

    • reducers(同步更新状态)

    • effects(异步逻辑)

    • subscriptions(订阅数据,如监听路由变化)

1.5 插件机制

  • 支持插件扩展(如 dva-loading 自动管理 loading 状态)。

二、基本使用

2.1 安装及创建

通过 npm 安装 dva-cli 并确保版本是 0.9.1 或以上。

// 全局安装
npm install dva-cli -g 
// 判断是否安装成功
dva -a

安装完 dva-ci 之后,就可以通过 dva new 创建新应用。

// 创建应用
dva new my-dva
// 进入目录并安装模块
cd my-dva
npm install

运行dva项目

npm start

2.2 目录结构

2.3 路由使用

// src/router.jsimport React from "react";
import { Router, Route, Switch } from "dva/router";
import IndexPage from "./routes/IndexPage";
import UserPage from "./routes/UserPage";function RouterConfig({ history }) {return (<Router history={history}><Switch><Route path="/" exact component={IndexPage} /><Route path="/user" exact component={UserPage} /></Switch></Router>);
}export default RouterConfig;
// src/routes/UserPage.jsimport React from "react";
import { Link } from "dva/router";
export default function UserPage(props) {console.log(props);const handleClick = () => {props.history.push("/"); //函数式组件可以使用useNavigate};return (<div><div>用户页</div><Link to="/">跳转到首页</Link><button onClick={handleClick}>点击跳转到首页</button></div>);
}

2.4 状态管理 models_reducer(同步)(以计数器为例)

2.4.1 创建model

// src/model/count.jsexport default {// 命名空间namespace: "count",// 状态state: {sum: 0,},// 同步操作reducers: {increment(state, action) {// 这里不能直接修改state返回,需要拷贝一个新的let nState = JSON.parse(JSON.stringify(state));nState.sum += action.data.num;return nState;},decrement(state, action) {// 这里不能直接修改state返回,需要拷贝一个新的let nState = JSON.parse(JSON.stringify(state));nState.sum += action.data.num;return nState;},},
};

2.4.2 引入model

// src/index.jsimport dva from "dva";
import "./index.css";// 1. Initialize
const app = dva();// 2. Plugins
// app.use({});// 3. Model
// app.model(require('./models/example').default);
// 引入Model
app.model(require("./models/count").default);// 4. Router
app.router(require("./router").default);// 5. Start
app.start("#root");

2.4.3 使用connect进行同步操作

// src/routes/CountPage.jsimport React from "react";
import { connect } from "dva";
function CountPage(props) {console.log(props);const { sum, dispatch } = props;const inc = (num) => {dispatch({ type: "count/increment", data: { num } });};const dec = (num) => {dispatch({ type: "count/decrement", data: { num } });};return (<div><div>{sum}</div><button onClick={() => inc(1)}>+1</button><button onClick={() => dec(-2)}>-2</button></div>);
}const mapStateToProps = (state) => {return {sum: state.count.sum, // count是命名空间,num是状态};
};export default connect(mapStateToProps)(CountPage);

2.5 状态管理 models_effects(异步)

2.5.1 修改model

// src/model/count.jsexport default {// 命名空间namespace: "count",// 状态state: {sum: 0,},// 同步操作reducers: {increment(state, action) {// 这里不能直接修改state返回,需要拷贝一个新的let nState = JSON.parse(JSON.stringify(state));nState.sum += action.data.num;return nState;},decrement(state, action) {// 这里不能直接修改state返回,需要拷贝一个新的let nState = JSON.parse(JSON.stringify(state));nState.sum += action.data.num;return nState;},},// 异步操作effects: {// 这里第一个结构赋值的data 要与dispatch一致*fetchIncrement({ data }, { put, call }) {// 异步操作,这里假设是1s延迟,会将结果返回给res// call方法异步操作,第1个是函数,第2个是传参const res = yield call((_) => {return new Promise((resolve) => {setTimeout(() => {resolve(_);}, 1000);});}, data);// 获得结果后调用同步方法,修改状态yield put({ type: "increment", data: { num: res.num } });},},
};

2.5.2 异步操作

// src/routes/CountPage.jsimport React from "react";
import { connect } from "dva";
function CountPage(props) {console.log(props);const { sum, dispatch } = props;const inc = (num) => {dispatch({ type: "count/increment", data: { num } });};const dec = (num) => {dispatch({ type: "count/decrement", data: { num } });};const fetchInc = (num) => {dispatch({ type: "count/fetchIncrement", data: { num } });};return (<div><div>{sum}</div><button onClick={() => inc(1)}>+1</button><button onClick={() => dec(-2)}>-2</button><button onClick={() => fetchInc(2)}>异步+2</button></div>);
}const mapStateToProps = (state) => {return {sum: state.count.sum, // count是命名空间,num是状态};
};export default connect(mapStateToProps)(CountPage);

2.6 订阅监听(subscriptions)(以检查登录状态为例)

// src/models/global.jsexport default {// 命名空间namespace: "global",// 状态state: {},subscriptions: {setup({ dispatch, history }) {// 初始化监听const unlisten = history.listen((location) => {console.log("路由变化:", location.pathname);// 示例:检查登录状态const token = localStorage.getItem("token");if (!token && location.pathname !== "/login") {history.push("/login");}});// 返回取消监听函数(可选)return () => unlisten();},},
};

2.7 模拟数据(mock)

2.7.1 创建mock

my-dva/mock.js

注意:不在src下,是在项目根目录下

module.exports = {"GET /api/mockData": (req, res) => {console.log(req);res.send({name: "喜羊羊",});},
};

2.7.2 注册mock

./.roadhogrc.mock.js

注意:不在src下,是在项目根目录下

export default {...require("./mock/testMock"),
};

src/serivces/example.js

import request from "../utils/request";// 注册mock接口
export function testMock() {return request("/api/mockData");
}

2.7.3 获取数据

import React from "react";
import { Link } from "dva/router";
import { testMock } from "../services/example";
export default function UserPage(props) {testMock().then((res) => {console.log(res);});const handleClick = () => {props.history.push("/"); //函数式组件可以使用useNavigate};return (<div><div>用户页</div><Link to="/">跳转到首页</Link><button onClick={handleClick}>点击跳转到首页</button></div>);
}

http://www.lqws.cn/news/448723.html

相关文章:

  • SM3算法C语言实现(无第三方库,带测试)
  • C++容器之 forward_list (单向链表)使用说明
  • Python 数据分析与可视化 Day 2 - 数据清洗基础
  • 基于深度学习的特征映射模块(FMS)实现与分析
  • 医疗AI大数据处理流程的全面解析:从数据源到应用实践
  • Spring IOC详解:从原理到实战
  • .NET基于类名约定的自动依赖注入完整指南
  • 【AI时代速通QT】第二节:Qt SDK 的目录介绍和第一个Qt Creator项目
  • node.js在vscode的配置
  • 大气商务工作汇报总结PPT模版分享
  • 华为云Flexus+DeepSeek征文 | 利用Dify平台构建多智能体协作系统:从单体到集群的完整方案
  • 以太坊节点搭建私链(POA)
  • davinci本地启动
  • 全面掌握 C++ 基础:关键特性与进化
  • uni-app-配合iOS App项目开发apple watch app
  • 巧用云平台API实现开源模型免费调用的实战教程
  • 电子电气架构 --- 软件供应商如何进入OEM体系
  • Git 命令全景图:从 clone 到 merge 的完整流程解析
  • 基于深度学习的智能视频行为识别系统:技术与实践
  • 【音视频 | RTP】RTP协议详解(H.264的RTP封包格式、AAC的RTP封包格式)
  • CSS3 3D 转换
  • GitHub Copilot 是什么,怎么使用
  • 上海人工智能实验室明珠湖会议首开,解答AI前沿疑问,推进科学智能
  • 【新手向】GitHub Desktop 的使用说明(含 GitHub Desktop 和 Git 的功能对比)
  • java面试题02访问修饰符有哪些?区别是什么?
  • 如何自建服务器并开启公网IP:本地内网网址让外网访问详细教学
  • 华为CE交换机抓包
  • 如何导出和迁移离线 Conda 环境
  • Java八股文——数据结构「排序算法篇」
  • 【目标检测】什么是目标检测?应用场景与基本流程