通过返回的key值匹配字典中的value值

发布于:2025-02-27 ⋅ 阅读:(11) ⋅ 点赞:(0)

需求

页面中上面搜索项有获取字典枚举接口,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就行,根本不用上面那些,先都记录上,后期根据需求灵活应用吧