参考其它文章编写了一个简单的Vue3字典管理插件
import {ref} from 'vue'
import {listDictItem} from '@/api/system/dict.ts'
// 使用DEMO
// Script 使用
// const dictList = inject('dict').getDict('states')
// const dict = inject('dict').getDict('btdd','key')
// Template 使用
// <span>{{ $dict('btdd','key') }}</span>
export default {
install(app) {
const state = {}
const map = new Map()
const getDictData = async (dictName) => {
try {
// 替换为你的接口异步请求
const res = await listDictItem({
dictType: dictName,
pageNum: 1,
pageSize: 1000,
})
state[dictName].value = res.list.map((item) => {
return {
label: item.dictName,
value: item.dictValue
}
})
// 触发所有订阅事件
const callbacks = map.get(dictName)
if (callbacks && Array.isArray(callbacks)) {
callbacks.forEach(callback => callback())
}
} finally {
// 字典已被缓存,可以放心移除记录,防止内存泄漏(箭头函数会被GC)
map.delete(dictName)
}
}
/**
* 获取字典数据
* @param {*} dictName
* @param {*} key
* @returns
*/
const getDict = (dictName, key = null) => {
const value = ref('')
// 如果数据已经加载完成,直接返回
if (dictName in state) {
if (key !== null) {
if (state[dictName].value.length > 0) {
value.value = state[dictName].value.find((item) => item.label === key)?.value
} else {
// 数据还在加载中,添加到订阅队列
// 利用数组处理多次并发订阅时后面订阅会覆盖前面订阅的问题
if (!map.has(dictName)) {
map.set(dictName, [])
}
map.get(dictName).push(() => {
// 根据异步获取的实际情况赋值
value.value = state[dictName].value.find((item) => item.label === key)?.value
})
}
return value
} else {
return state[dictName]
}
} else {
state[dictName] = ref([])
getDictData(dictName).then(() => {
if (key !== null) {
// 根据异步获取的实际情况赋值
value.value = state[dictName].value.find((item) => item.label === key)?.value
}
})
if (key !== null) {
return value
} else {
return state[dictName]
}
}
}
app.config.globalProperties.$dict = getDict
app.provide('dict', {getDict})
}
全局使用引入参考Vue3 插件使用文档