最近在学习若依系统的框架,其中发现一个很奇怪的事情,网上查询很多地方,也是一知半解。
网上搜索的结果如下,大家可以先看看:
[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))
}
//=============第一次学着写博文,希望大家多鼓励=====================//
版权归原作者 w4sevens 所有, 如有侵权,请联系我们删除。