若依前端字典实现全解:Vue2 vs Vue3

61 阅读3分钟
image.png

1. 字典是什么

  • 业务中的枚举数据集合,例如“性别:男/女”“状态:正常/停用”。
  • 前端诉求:一次获取,多处复用;改了后端字典能及时刷新;避免同一字典被重复请求。

2. Vue2 版本实现

核心角色

  • dict 全局 mixin:在组件 created 时自动拉取声明的字典。
  • Vuex dict 模块:前端缓存,提供 get/set/remove/clean
  • 接口 getDicts(dictType):请求 /system/dict/data/type/{dictType}

典型流程(自动拉取)

  1. 组件声明需要的字典类型:
    export default {
      name: "User",
      dicts: ["sys_normal_disable", "sys_user_sex"],
    };
    
  2. created 钩子(mixin 注入)触发:
    • 遍历 dicts
      • 先查 Vuex 缓存 getDict(dictType),命中直接用。
      • 未命中则请求 /system/dict/data/type/{dictType}
  3. 响应返回:
    • 映射为 { label, value, elTagType, elTagClass }
    • 写入缓存 setDict(dictType, mappedArray)
    • 注入组件实例 this.dict.type[dictType],模板可直接使用。
  4. 缓存失效:
    • 字典数据增删改后调用 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}

典型流程(按需拉取)

  1. 组件 setup 调用:
    const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
    
  2. useDict 对每个 dictType
    • 先查 Pinia 缓存 getDict(dictType);命中则直接返回。
    • 未命中则请求接口。
  3. 响应返回:
    • 映射为 { label, value, elTagType, elTagClass }
    • 写入缓存 setDict(dictType, mappedArray)
    • 更新返回的 ref,模板自动刷新。
  4. 缓存失效:
    • 字典数据增删改后调用 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.dictthis.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;
下一次使用,自动重拉最新。