当前位置: 首页 > 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.lryc.cn/news/572971.html

相关文章:

  • kubeadm worker节点加入master失败
  • android gradle的优化
  • Ruoyi(若依)整合websocket实现信息推送功能(消息铃铛)
  • 01-JS资料
  • Vue.js状态管理: 使用Vuex实现状态统一管理的最佳实践
  • 容器技术技术入门与Docker环境部署
  • 传输层协议UDP/TCP
  • 【工具教程】识别PDF中文字内容,根据文字内容对PDF批量重命名,提取识别PDF内容给图片重新命名的操作步骤和注意事项
  • C#上位机实现报警语音播报
  • Spring Boot + MyBatis + Vue:全栈开发中的最佳实践
  • vue通过打开新标签页打开某个路由
  • day43-硬件学习之ARM基础知识
  • 【蓝牙】Qt4中向已配对的手机发送PDF文件
  • JavaWeb前端部分
  • Centos 离线部署(MQTT)EMOX脚本并设置开机自启
  • 微软应用商店打不开怎么办2025,打开TLS1.3
  • 第五章 中央处理器
  • GoogLeNet:图像分类神经网络的深度剖析与实践
  • 大内存对电脑性能有哪些提升
  • 1.容器技术与docker环境部署
  • QEMU学习之路(10)— RISCV64 virt 使用Ubuntu启动
  • 微电网系列之微电网的运行控制
  • Python 中设置布尔值参数为 True 来启用验证
  • Unity3D仿星露谷物语开发67之创建新的NPC
  • 【工具教程】识别PDF中文字内容,批量识别文字并保存到Excel表格中的操作步骤和方法
  • 机器学习流量识别(pytorch+NSL-KDD+多分类建模)
  • 信创 CDC 实战|国产数据库的数据高速通道:OceanBase 实时入仓 StarRocks
  • vue3 el-select @change (val) 多参数传值操作
  • KVM -- 虚拟化技术
  • DDoS防护体系构建——从基础限速到智能调度