dva.js
dva.js 是一个基于 redux、redux-saga 和 react-router 的轻量级前端框架,由蚂蚁金服团队开发。它旨在简化 React 应用的开发过程,提供了一套开箱即用的最佳实践,使得开发者可以更专注于业务逻辑的实现。dva.js 通过集成这些库,提供了一个更加简洁和高效的开发体验。
dva.js 的主要特点
- 数据流方案:内置了类似 Redux 的数据流机制,并使用
redux-saga来处理副作用(如异步操作),提供了比传统 Redux 更简洁的 API。 - 路由管理:集成了
react-router,支持动态路由配置,简化了页面导航和 URL 管理。 - 自动加载模型:支持按需加载模型,优化了应用的初始加载时间。
- 国际化支持:内置 i18n 支持,方便进行多语言开发。
- 热更新:支持 Webpack 的热模块替换 (HMR),提高了开发效率。
- 插件系统:拥有丰富的插件生态,可以通过安装插件扩展功能。
- TypeScript 支持:良好的 TypeScript 集成,提供更严格的类型检查和支持。
- CLI 工具:提供了命令行工具
dva-cli,用于快速创建项目和生成代码。
安装和使用 dva.js
创建新项目
你可以通过 dva-cli 快速创建一个新的 dva.js 项目:
bash
npm install -g dva-cli
dva new my-app
cd my-app
npm start这将创建一个基础的 dva.js 项目结构,并启动开发服务器。
项目结构
一个典型的 dva.js 项目结构如下:
my-app/
├── config/ # 配置文件目录
├── mock/ # Mock 数据目录
├── public/ # 公共资源目录
├── src/
│ ├── assets/ # 资源文件目录
│ ├── components/ # 可复用组件目录
│ ├── layouts/ # 页面布局目录
│ ├── models/ # Dva model 文件目录
│ ├── pages/ # 页面组件目录
│ ├── services/ # API 请求服务目录
│ └── utils/ # 实用工具函数目录
├── .umirc.ts # 主配置文件 (如果使用 Umi)
└── package.json # 依赖管理文件核心概念
Model
dva.js 中的核心概念是 Model,它是用来组织状态(state)、视图(view)和数据交互逻辑的地方。每个 model 包含以下属性:
- namespace:命名空间,用于区分不同的 model。
- state:当前的状态。
- reducers:纯函数,接收 action 并返回新的 state。
- effects:处理副作用(如异步操作)的函数,通常使用
redux-saga。 - subscriptions:监听某些事件并触发 effects 或 reducers。
示例:创建一个简单的模型
javascript
// src/models/example.js
export default {
namespace: "example",
state: {
count: 0,
},
reducers: {
increment(state) {
return { ...state, count: state.count + 1 };
},
decrement(state) {
return { ...state, count: state.count - 1 };
},
},
effects: {
*incrementAsync(action, { call, put }) {
yield call(delay, 1000); // 模拟异步请求
yield put({ type: "increment" });
},
},
subscriptions: {
setup({ history }) {
// 监听 URL 变化或其他事件
},
},
};
function delay(timeout) {
return new Promise((resolve) => setTimeout(resolve, timeout));
}Router
dva.js 使用 react-router 进行路由管理,你可以在 src/router.js 中定义路由配置。
示例:定义路由
javascript
// src/router.js
import React from "react";
import dynamic from "dva/dynamic";
const Home = dynamic(() => import("./pages/Home"));
const About = dynamic(() => import("./pages/About"));
export default function Router({ history }) {
return (
<Router history={history}>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
</Switch>
</Router>
);
}Service
service 用于封装 API 请求逻辑,使你的模型更加清晰和可维护。
示例:创建一个 service
javascript
// src/services/api.js
export async function fetchUser(id) {
const response = await fetch(`/api/user/${id}`);
return await response.json();
}使用 Hooks
从 dva v2 开始,dva 支持使用 React Hooks 来访问 store 和 dispatch actions,这使得函数组件可以直接与 dva 的数据流集成。
示例:在函数组件中使用 Hooks
javascript
// src/pages/Home.jsx
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "dva";
import styles from "./Home.module.css";
function Home() {
const dispatch = useDispatch();
const count = useSelector((state) => state.example.count);
useEffect(() => {
dispatch({ type: "example/incrementAsync" });
}, [dispatch]);
return (
<div className={styles.home}>
<p>Count: {count}</p>
<button onClick={() => dispatch({ type: "example/increment" })}>
Increment
</button>
<button onClick={() => dispatch({ type: "example/decrement" })}>
Decrement
</button>
</div>
);
}
export default Home;插件
dva 提供了丰富的插件来扩展其功能。你可以通过 app.use() 方法添加插件,或者直接安装官方或第三方插件。
示例:添加插件
javascript
// src/index.js
import dva from "dva";
import createLoading from "dva-loading";
const app = dva();
// 添加插件
app.use(createLoading());
// 加载模型
app.model(require("./models/example").default);
// 启动应用
app.start("#root");总结
dva.js 是一个强大的前端框架,特别适合构建复杂的 React 应用程序。它不仅简化了状态管理和异步操作的处理,还提供了便捷的路由管理和国际化支持。如果你正在寻找一种现代化的方式来构建 React 应用,dva.js 是一个非常好的选择。