vue字典取键值对([vue 进阶] 关于dicts字典的用法)
最近在学习若依系统的框架 ,其中发现一个很奇怪的事情 ,网上查询很多地方 ,也是一知半解 。
网上搜索的结果如下 ,大家可以先看看:
[vue 进阶] 关于dicts字典的用法_小钿钿不忘初心_的博客-CSDN博客前言在使用若依框架开发小项目的时候 ,发现在项目中频繁使用到字典 ,原本代码中的dicts没有深入研究 ,故自己写了一个混入来实现想要的字典获取功能 。但是觉得每次切换页面都需要调用一下 ,而且每个系统都有一个mixins混入文件 ,感觉维护起来稍显繁琐 。继而研究了一下dicts的用法 ,记录一下使用过程 。1.首先确定字典的接口 ,在若依框架中如下 ,具体可根据自己后端提供的字典接口进行修改// 根据字典类型查询字典数据信息export function getDicts(dictType) { return rhttps://blog.csdn.net/u013034585/article/details/122185684所以花了一天时间去研究若依中关于dicts的使用 。
简单的说就是:
将字典做成了插件,添加到了Vue全局中 ,然后使用混入技术mixin ,将dict的内容混入其中,然后每一个组件就都可以使用 ,但是我们发现并没有定义dict ,很多人会觉得很奇怪 。
<el-select v-model="form.sex" placeholder="请选择性别"> <el-option v-for="dict in dict.type.sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value" ></el-option> </el-select>这里就是 ,使用的dict好像没有定义啊???
但是我们发现 ,有这样的东西 。
export default { name: "User", // 使用字典属性 dicts: [sys_normal_disable, sys_user_sex], components: { Treeselect }, }是不是很迷糊?下面我们取dict的源码中去找找看?
-------------------------------以下是源码 ,已经有注释了 ,大家可以自己看-----------------
将dict相关的属性封装成组件 ,然后使用插件的形式放入Vue ,通过Vue实现全局混入 ,这样在任何地方就可以使用dict属性使用字典
第一步:字典插件初始化
// 字典数据组件----------->main.js import DictData from @/components/DictData // 字典组件挂载到Vue上当做插件使用 DictData.install()第二步:字典组件定义
注意 ,这里vue.use方法的第二个参数是option参数表 ,这个值是可选项 ,使用use函数的时候,将会作为参数传递进来 ,可以搜索use源码:const args = toArray(arguments, 1) ,这里将参数在赋给字典插件
import Vue from vue import DataDict from @/utils/dict import {getDicts as getDicts} from @/api/system/dict/data // 这是查询字典的方法 function install() { // 使用vue挂载DataDict插件,这里插件做成了函数形式 ,不需要install方法 ,直接use即可 Vue.use(DataDict, { metas: { *: { labelField: dictLabel, valueField: dictValue, request(dictMeta) { return getDicts(dictMeta.type).then(res => res.data) }, }, }, }) } export default { install, }第三步:自定义字典函数
这里主要是将自定义内容挂载到vue实例当中去 ,充分使用mixin技术实现
export default function(Vue, options) { // 1. 用插件参数替换默认配置参数 mergeOptions(options) // Vue全局混入dict属性 Vue.mixin({ data() { // 注意这里this.$options表示vue实例中data以外定义的属性 ,所以用户需要使用的时候 ,只需要在实例中加dicts属性列表即可 if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) { return {} } // 这里将结果返回给了dict对象 ,所以使用dict对象可以实现数据使用 const dict = new Dict() dict.owner = this return { dict } }, created() { // 如果当前组件没有定义属性列表dicts,那么就没有混入dict属性,this.dict就不存在 ,直接返回 ,不调用dict.init() if (!(this.dict instanceof Dict)) { return } options.onCreated && options.onCreated(this.dict) // dict的初始化 ,这里的$options.dicts是当前组件的dicts属性 ,包含用户自定义属性值列表type // init函数执行完毕 ,那么所欲的dict数据均加载完毕 this.dict.init(this.$options.dicts).then(() => { // 如果初始化组件的时候 ,参数中定义onReady函数,那么此时就会调用 options.onReady && options.onReady(this.dict) this.$nextTick(() => { // 触发dictReady事件 this.$emit(dictReady, this.dict) // 调用组件实例中的methods属性 ,如果其中的onDictReady存在 ,那么就执行他,并把dict作为参数传递进去 ,并执行 if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) { this.$options.methods.onDictReady.call(this, this.dict) } }) }) }, })}首先 ,看看mergeOptions(options)函数干了什么
export const options = { metas: { *: { /** * 字典请求 ,方法签名为function(dictMeta: DictMeta): Promise */ request: (dictMeta) => { console.log(`load dict ${dictMeta.type}`) return Promise.resolve([]) }, /** * 字典响应数据转换器 ,方法签名为function(response: Object, dictMeta: DictMeta): DictData */ responseConverter, labelField: label, valueField: value, }, }, /** * 默认标签字段 */ DEFAULT_LABEL_FIELDS: [label, name, title], /** * 默认值字段 */ DEFAULT_VALUE_FIELDS: [value, id, uid, key], } export function mergeOptions(src) { // 以递归的形式用src中属性值去替换options中同位置的值 ,没有的话就使用默认options mergeRecursive(options, src) } // 数据合并 export function mergeRecursive(source, target) { for (var p in target) { try { if (target[p].constructor == Object) { source[p] = mergeRecursive(source[p], target[p]); } else { source[p] = target[p]; } } catch (e) { source[p] = target[p]; } } return source; }以上我们可以得出结论 ,mergeOptions就是将src和options合并 ,然后返回 ,其中src有得都会对应给options ,src中没有的则默认使用options中的属性 ,结果如下:
// 1.内置的options参数 export const options = { metas: { *: { request: (dictMeta) => { console.log(`load dict ${dictMeta.type}`) return Promise.resolve([]) }, responseConverter, labelField: label, valueField: value, }, }, DEFAULT_LABEL_FIELDS: [label, name, title], DEFAULT_VALUE_FIELDS: [value, id, uid, key], } // 2. 用户自定义插件时传入的参数 src = { metas: { *: { labelField: dictLabel, valueField: dictValue, request(dictMeta) { return getDicts(dictMeta.type).then(res => res.data) }, }, }, } // 3.合并之后的结果 { metas: { *: { request(dictMeta) { return getDicts(dictMeta.type).then(res => res.data) }, responseConverter, labelField: dictLabel, valueField: dictValue, }, }, DEFAULT_LABEL_FIELDS: [label, name, title], DEFAULT_VALUE_FIELDS: [value, id, uid, key], } 其中responseConverter是自定义转换函数 ,如下:
function responseConverter(response, dictMeta) { const dicts = response.content instanceof Array ? response.content : response if (dicts === undefined) { console.warn(`no dict data of "${dictMeta.type}" found in the response`) return [] } return dicts.map(d => dictConverter(d, dictMeta)) } export default function(dict, dictMeta) { const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS) const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS) return new DictData(dict[label], dict[value], dict) } /** * 确定字典字段 * @param {DictData} dict * @param {...String} fields */ function determineDictField(dict, ...fields) { return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f)) }//=============第一次学着写博文 ,希望大家多鼓励=====================//
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!