当前位置: 首页 > 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>);
}

相关文章:

  • 【redis】客户端
  • LVS负载均衡群集:Nginx+Tomcat负载均衡群集
  • 4-STM32F103的串口中断与空闲中断接收数据
  • 装配基本操作与标准配合关系-装配体设计技能(1)
  • 【案例拆解】米客方德 SD NAND 在车联网中(有方模块)的应用:破解传统 TF 卡振动脱落与寿命短板
  • 地标“金”字招牌再升级:赤水金钗石斛携手世酒中菜开启新纪元
  • AI Agent开发与安全
  • 【网络安全】ios逆向一般整理
  • Python 中设置布尔值参数为 True 来启用验证
  • 全球首款5G-A人形机器人亮相,通信与AI融合进入新阶段
  • ACR窃密木马改头换面,更名重构后规避能力升级
  • RPGMZ游戏引擎 如何手动控制文字显示速度
  • 8年java开发从零学习人工智能(深度学习)--pp飞桨(百度自研开源框架)
  • 领码 SPARK 融合平台赋能工程建设行业物资管理革新——数智赋能,重塑中国模式新范式
  • leetcode-3443. K次修改后的最大曼哈顿距离
  • Vue 滑动验证组件
  • OPENGLPG第九版学习 - 纹理与帧缓存 part1
  • conda导出环境文件requirements.txt
  • Python OpenCV 模板匹配的一些应用场景和方法思考,浅析KAZE特征匹配对比
  • Odoo 18进阶开发:打造专业级list,kanban视图Dashboard
  • 网站建设管理专员/360提交网站收录入口
  • 网站建设公司哪个好呀/百度入口网站
  • 小程序源码网站论坛/网络软文推广案例
  • 怎样修改网站关键词/百度云盘官网
  • 网站建设做哪 个会计科目/可以免费推广的平台
  • 域名 网站 区别/免费的模板网站