- 只要你在
.umirc.ts开启了dva: {},Umi 会自动内置dva-loading插件,不需要手动新建loading.jsmodel; - 插件内部自动注入一套 reducer、监听所有
effects异步函数,自动维护全局loading数据; - 全局根
state顶层直接多出一个loading对象,所以可以直接写state => state.loading。
底层原理(插件自动劫持 effect)
插件利用 dva 的 onEffect 钩子:
- 任意
yield call()发起接口请求前 → 自动 dispatch action,标记 loading = true; - 接口请求成功 / 失败结束后 → 自动 dispatch action,标记 loading = false; 全程不用你手动写
setLoading(true/false)。
二、loading 对象完整结构(打印看得到)
loading = {
global: false, // 全局:任意接口在请求就为 true
models: {
user: false, // user 模块任意effect请求中=true
goods: false
},
effects: {
'user/fetchInfo': false, // 精准单个接口 loading
'goods/getList': false
}
}
三、每个字段作用 & 业务使用场景
1. loading.global(全局转圈、全局遮罩)
只要项目里任意接口正在请求,值为 true。
const loading = useSelector(state => state.loading);
// 全局loading遮罩
<Spin spinning={loading.global}>{页面内容}</Spin>
2. loading.models.xxx(按模块控制 loading)
xxx 是 model 的 namespace,该 model 下任意 effect 请求中 = true。
// user模型任意接口加载时,表格转圈
const userLoading = useSelector(state => state.loading.models.user);
<Table loading={userLoading} />
3. 精准单个接口 loading
loading.effects['namespace/effect名'](精准单个接口 loading)
只监听某一个具体接口,适合同一页面多个按钮分别 loading:
// 只监听 user/fetchList 这个effect
const tableLoading = useSelector(state => state.loading.effects['user/fetchList']);
const submitLoading = useSelector(state => state.loading.effects['user/save']);
<Table loading={tableLoading} />
<Button loading={submitLoading}>提交</Button>
- 全局统一加载动画、页面遮罩;
- 控制 Table、Modal、Form 的加载转圈;
- 防止重复点击提交按钮(loading 为 true 时禁用按钮);
- 骨架屏、加载提示文案统一管理。
完整组件示例:
import { useSelector, useDispatch } from 'dva';
import { Spin, Table, Button } from 'antd';
export default function UserPage() {
const dispatch = useDispatch();
// 获取整套loading状态
const loading = useSelector(state => state.loading);
// 精准取当前表格接口loading
const tableLoading = loading.effects['user/fetchList'];
const loadData = () => {
dispatch({ type: 'user/fetchList' });
};
return (
<Spin spinning={loading.global}>
<Button onClick={loadData} loading={tableLoading}>
刷新列表
</Button>
<Table loading={tableLoading} />
</Spin>
);
}
五、常见疑问
1. 为什么我项目里找不到 loading.js model?
因为是框架内置插件自动生成,不是手动创建的 src/models 文件,源码在 umi 内部插件里,项目目录看不到。
2. 关闭 dva 后 loading 就消失
.umirc.ts 如果删掉 dva:{immer:true},dva 插件失效,state.loading 会直接不存在,访问会报错。
3. 为什么不用自己维护 loading 变量?
传统 redux 需要每个 effect 手动写:
// 传统写法,冗余
yield put({type:'user/setLoading', payload:true})
yield call(request, '/api')
yield put({type:'user/setLoading', payload:false})
dva-loading 全自动处理,省去重复代码。




