目錄
一、安裝依賴
二、Dva注冊model方式
2.1 自動注冊models
2.2 手動注冊model方式
三、創建 dva 實例
四、創建 model
五、在組件中使用
六、動態加載Dva Model
Dva 是一個基于 redux 和 redux-saga 的輕量級前端框架,可以方便地在 React 應用中管理狀態。下面是將 Dva 接入 create-react-app 項目的步驟:
一、安裝依賴
? ? ? ? 在react-react-app項目目錄中安裝 dva 相關依賴:
npm install dva --save
# 或者使用 yarn
yarn add dva
二、Dva注冊model方式
2.1 自動注冊models
????????Dva 本身不會自動識別特定的?models
?文件夾或?model.js
?文件,但官方推薦以下約定俗成的結構:
src/├── models/ # 全局 model 目錄│ ├── user.js # 用戶 model│ └── product.js # 產品 model└── pages/├── Home/│ ├── model.js # 頁面級 model (可選)│ └── index.js└── About/├── model.js└── index.js
2.2 手動注冊model方式
????????Dva 需要顯式注冊?model 才會生效,主要有以下幾種注冊方式:
- 初始化時注冊
// src/index.js
app.model(require('./models/user').default);
- 動態注冊
// 在組件或路由加載時
useEffect(() => {app.model(require('./models/product').default);
}, []);
三、創建 dva 實例
修改?src/index.js
?文件:
import React from 'react';
import dva from 'dva';
import createHistory from 'history/createBrowserHistory';
import App from './App';
import './index.css';// 1. Initialize
const app = dva({history: createHistory(),
});// 2. Plugins (可選)
// app.use({});// 3. Model (可以在這里注冊全局model)
// app.model(require('./models/example').default);// 4. Router
app.router(() => <App />);// 5. Start
app.start('#root');
四、創建 model
在?src/models
?目錄下創建一個 model 文件,例如?counter.js
:
// 標準的 model 文件示例 (models/counter.js)
//export default {
// namespace: 'user', // 必須的唯一標識
// state: {}, // 必須的初始狀態
// reducers: {}, // 同步修改 state 的方法
// effects: {}, // 異步處理邏輯
// subscriptions: {} // 訂閱數據源
//};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(_, { call, put }) {yield call(delay, 1000);yield put({ type: 'add' });},},
};function delay(timeout) {return new Promise(resolve => {setTimeout(resolve, timeout);});
}
五、在組件中使用
方法一:connect
import React from 'react';
import { connect } from 'dva';function Counter({ count, dispatch }) {return (<div><h2>Count: {count}</h2><button onClick={() => dispatch({ type: 'counter/add' })}>+</button><button onClick={() => dispatch({ type: 'counter/minus' })}>-</button><button onClick={() => dispatch({ type: 'counter/addAsync' })}>Add Async</button></div>);
}function mapStateToProps(state) {return {count: state.counter.count,};
}export default connect(mapStateToProps)(Counter);
方法二:React Hooks(useSelector、useDispatch)
import React from 'react';
import { useSelector, useDispatch } from 'dva';function Counter() {// 使用 useSelector 獲取 state 中的 counter 數據const count = useSelector(state => state.counter.count);// 使用 useDispatch 獲取 dispatch 方法const dispatch = useDispatch();return (<div><h2>Count: {count}</h2><button onClick={() => dispatch({ type: 'counter/add' })}>+</button><button onClick={() => dispatch({ type: 'counter/minus' })}>-</button><button onClick={() => dispatch({ type: 'counter/addAsync' })}>Add Async</button></div>);
}export default Counter;
六、動態加載Dva Model
方法一:使用useEffect + app.model()
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'dva';export default function CounterPage() {const dispatch = useDispatch();const count = useSelector(state => state.counter.count);useEffect(() => {// 動態加載 modelapp.model(require('../models/counter').default);// 組件卸載時取消注冊 model(可選)return () => {app.unmodel('counter');};}, [app]);return (<div><h2>Count: {count}</h2><button onClick={() => dispatch({ type: 'counter/add' })}>+</button></div>);
}
方法二:使用dynamic
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'dva';export default function CounterPage() {const dispatch = useDispatch();const count = useSelector(state => state.counter.count);useEffect(() => {// 動態加載 modeldispatch({type: '@@dva/dynamicLoad',payload: {models: () => [import('../models/counter')],},});return () => {// 可以在這里取消 model(如果需要)};}, [dispatch]);return (<div><h2>Count: {count}</h2><button onClick={() => dispatch({ type: 'counter/add' })}>+</button></div>);
}