1. React DVA 示例
在 DVA 中,你需要将状态、同步修改、异步请求严格分离,并使用 Generator 函数处理异步。
Model 定义:
export default {
namespace: 'user',
state: {
userInfo: null,
loading: false
},
reducers: {
// 同步修改:必须返回新对象(不可变性)
saveUser(state, { payload }) {
return { ...state, userInfo: payload, loading: false };
},
setLoading(state, { payload }) {
return { ...state, loading: payload };
}
},
effects: {
// 异步操作:使用 Generator 函数
*fetchUser({ payload }, { call, put }) {
yield put({ type: 'setLoading', payload: true });
const response = yield call(api.getUserInfo, payload);
yield put({ type: 'saveUser', payload: response.data });
}
}
};
组件使用:
import { connect } from 'dva';
const UserProfile = ({ user, dispatch }) => {
useEffect(() => {
// 触发 effects 中的异步操作
dispatch({ type: 'user/fetchUser', payload: { id: 1 } });
}, []);
return <div>{user.loading ? '加载中...' : user.userInfo?.name}</div>;
};
// 通过 connect 映射 state 到组件的 props
export default connect(({ user }) => ({ user }))(UserProfile);
2. Vue (Pinia) 示例
在 Pinia 中,状态修改和异步逻辑可以合并在 actions 中,代码更加直观和紧凑。
Store 定义:
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: null,
loading: false
}),
actions: {
// 异步和同步操作直接写在一起
async fetchUser(id) {
this.loading = true; // 直接修改 state(Pinia 底层自动追踪)
const response = await api.getUserInfo(id);
this.userInfo = response.data; // 直接赋值
this.loading = false;
}
}
});
组件使用:
<script setup>
import { storeToRefs } from 'pinia';
import { useUserStore } from '@/stores/user';
const userStore = useUserStore();
// 使用 storeToRefs 解构保持响应式
const { loading, userInfo } = storeToRefs(userStore);
// 直接调用 action
userStore.fetchUser(1);
</script>
<template>
<div>{{ loading ? '加载中...' : userInfo?.name }}</div>
</template>
核心差异总结
- 异步语法:DVA 必须使用
*fetchUser(Generator) +yield call+yield put;Vue 只需要普通的async fetchUser+await。 - 状态修改:DVA 的
reducers必须return { ...state }返回新对象;Vue 的 Pinia 可以直接this.loading = true赋值。 - 组件绑定:DVA 需要
connect包裹组件并手动映射 props;Vue 只需useUserStore()引入即可,模板自动响应数据变化。




