需求
页面中上面搜索项有获取字典枚举接口,table表格中也有根据key匹配字典中的value
方案一
需要做到的要求
- 这里上面下拉列表是一个组件获取的字典,下面也是通过字典匹配,所以尽量统一封装一个函数,每个组件保证最少变动
- table表格中如果filters中更改,会获取多次接口,—使用闭包让只获取一次接口,节省性能
- filter中又是必须同步函数,异步函数报错,所以不能使用async,await
- 最好请求接口之后存储起来下次直接拿不用请求了
综上
utils/dictionary.js
import { getDicValue } from '@/api/systemManage'
import store from '@/store'
/**
* 获取字典数据
* @param {Boolean} hasAllOption 是否包含全部选项
*/
export function getDicValueList(dictClassCode, hasAllOption = true) {
const dictionaryCache = store.state.dictionary.dictionaryCache || {}
return new Promise((resolve, reject) => {
let optionList = []
if (dictionaryCache[dictClassCode]) {
const dicList = JSON.parse(JSON.stringify(dictionaryCache[dictClassCode]))
if (hasAllOption) {
optionList = [ { value: '', label: '全部' }, ...dicList]
} else {
optionList = [...dicList]
}
resolve(optionList)
} else {
getDicValue(dictClassCode).then(response => {
console.log('字典调用', dictClassCode)
const dicList = response.value || []
store.dispatch('dictionary/setDictionaryCache', { key: dictClassCode, value: dicList })
if (hasAllOption) {
optionList = [ { value: '', label: '全部' }, ...dicList]
} else {
optionList = [...dicList]
}
resolve(optionList)
}).catch(error => {
reject([])
})
}
})
}
/**
* 获取字典数据并返回一个闭包函数
* @param {string} dictClassCode 字典类代码
* @param {string} noTitle 默认值,当找不到匹配项时返回
* @returns {Promise<Function>} 返回一个闭包函数,该函数可以根据 value 获取 label
*/
export async function getDicValueName(dictClassCode, noTitle = "--") {
try {
const response = await getDicValueList(dictClassCode, false)
const listData = response || []
return (value) => {
let label = noTitle
listData.some(item => {
if (item.value === value) {
label = item.label
return true
}
})
return label
}
} catch (err) {
console.error(err)
return (value) => noTitle
}
}
下拉框组件
created () {
this.getOptionLists()
},
getOptionLists() {
if (this.dictClassCode) {
getDicValueList(this.dictClassCode).then(res => {
this.optionLists = res
})
} else {
this.optionLists = this.options
}
},
table组件中
<span>{{ filterStateName(scope.row.state) }}</span>
import { getDicValueName } from '@/utils/dictionary'
created() {
this.initDictionary()
},
methods: {
async initDictionary() {
try {
this.filterStateName = await getDicValueName('DC_DICTIONARY_STATE')
} catch (error) {
console.error('Failed to fetch dictionary:', error)
this.filterStateName = (value) => '--'
}
},
}
问题: 但是这种因为一进页面这两个组件都是去获取字典,所以还是从接口拿的数据,会调用两次接口
方案二(建议)
方案:接下来优化可以通过路由导航预加载,先获取字典之后,在加载页面
router.js
// 预加载字典
export function preloadDictionary(dictClassCodeList) {
const pList = []
dictClassCodeList.forEach(dictClassCode => {
const p = getDicValueList(dictClassCode)
pList.push(p)
})
return Promise.all(pList)
}
// 预加载字典
router.beforeEach((to, from, next) => {
if(to.meta && to.meta.dictClassCodeList&& to.meta.dictClassCodeList.length > 0) {
preloadDictionary(to.meta.dictClassCodeList).then(res => {
next()
})
} else {
next()
}
})
总结:其实这里都可以规定直接预加载字典,到页面直接使用加载后的字典,注册个全局filters就行,根本不用上面那些,先都记录上,后期根据需求灵活应用吧