1. 字典是什么
- 业务中的枚举数据集合,例如“性别:男/女”“状态:正常/停用”。
- 前端诉求:一次获取,多处复用;改了后端字典能及时刷新;避免同一字典被重复请求。
2. Vue2 版本实现
核心角色
- dict 全局 mixin:在组件
created时自动拉取声明的字典。 - Vuex
dict模块:前端缓存,提供get/set/remove/clean。 - 接口
getDicts(dictType):请求/system/dict/data/type/{dictType}。
典型流程(自动拉取)
- 组件声明需要的字典类型:
export default { name: "User", dicts: ["sys_normal_disable", "sys_user_sex"], }; created钩子(mixin 注入)触发:- 遍历
dicts:- 先查 Vuex 缓存
getDict(dictType),命中直接用。 - 未命中则请求
/system/dict/data/type/{dictType}。
- 先查 Vuex 缓存
- 遍历
- 响应返回:
- 映射为
{ label, value, elTagType, elTagClass }。 - 写入缓存
setDict(dictType, mappedArray)。 - 注入组件实例
this.dict.type[dictType],模板可直接使用。
- 映射为
- 缓存失效:
- 字典数据增删改后调用
removeDict(dictType)或cleanDict()。 - 失效后再进页面会重新请求。
- 字典数据增删改后调用
用法示例(模板)
<el-select v-model="form.status">
<el-option
v-for="d in dict.type.sys_normal_disable"
:key="d.value"
:label="d.label"
:value="d.value"
/>
</el-select>
<dict-tag :options="dict.type.sys_normal_disable" :value="row.status" />
3. Vue3 版本实现
核心角色
- 组合式
useDict(...dictTypes):按需拉取。 - Pinia
dict模块:前端缓存,get/set/remove/clean。 - 接口
getDicts(dictType):同样请求/system/dict/data/type/{dictType}。
典型流程(按需拉取)
- 组件
setup调用:const { sys_normal_disable } = proxy.useDict("sys_normal_disable"); useDict对每个dictType:- 先查 Pinia 缓存
getDict(dictType);命中则直接返回。 - 未命中则请求接口。
- 先查 Pinia 缓存
- 响应返回:
- 映射为
{ label, value, elTagType, elTagClass }。 - 写入缓存
setDict(dictType, mappedArray)。 - 更新返回的
ref,模板自动刷新。
- 映射为
- 缓存失效:
- 字典数据增删改后调用
useDictStore().removeDict(dictType)。 - “刷新缓存”按钮会
cleanDict()(同时后端刷新)。
- 字典数据增删改后调用
用法示例(模板)
<el-select v-model="form.status">
<el-option
v-for="d in sys_normal_disable"
:key="d.value"
:label="d.label"
:value="d.value"
/>
</el-select>
<dict-tag :options="sys_normal_disable" :value="row.status" />
4. Vue2 vs Vue3 对比
| 维度 | Vue2(mixin + Vuex) | Vue3(useDict + Pinia) |
|---|---|---|
| 取数方式 | 自动:声明 dicts 后在 created 批量拉取 | 按需:调用 useDict 时才拉取 |
| API 风格 | Options API,this.dict、this.getDicts | 组合式 API,const { xxx } = useDict(...) |
| 缓存 | Vuex 模块 | Pinia 模块 |
| 控制粒度 | 生命周期自动批量,可能“未用先取” | 用到再取,懒加载 |
| 侵入性 | 依赖全局 mixin,隐式注入 | 无 mixin,显式调用 |
| 冗余请求 | 可能因自动拉取多取 | 按需取,少冗余 |
| 可测试性 | mixin 隐式注入,单测需关注上下文 | 组合式函数更易单测 |
5. 使用攻略
- Vue2 项目:
- 在组件上写
dicts: ['xxx'],模板用dict.type.xxx。 - 改完数据后记得
removeDict('xxx')或点页面的“刷新缓存”。
- 在组件上写
- Vue3 项目:
const { xxx } = proxy.useDict('xxx'),模板直接用xxx。- 改完数据后
useDictStore().removeDict('xxx')或点“刷新缓存”。
6. 常见问题
- 会不会频繁请求?
先查缓存,只有未命中或缓存被清时才请求。 - 刷新浏览器后呢?
缓存在内存里,刷新页面会清空;首次进入会按需重新请求。 - 改了字典但页面没更新?
确认增删改后有调用removeDict(type)(或页面提供的刷新按钮)。
7. 总结
先查缓存,未命中再请求;
映射存缓存,响应式回填;
改了就 remove,刷新就 clean;
下一次使用,自动重拉最新。