最近在项目开发中遇到一个需求:即前端根据约定好的规则将一段描述匹配成可进行输入操作的表单,并将改变后的表单值按照原约定规则还原成JSON字符串返回给后端存储,以便下次拿到最新的描述。具体业务不多赘述,主要是提供一种开发思路,以下是案例展示与代码实现。
1.案例展示:
2.代码展示:
html部分(仅展示表单部分):
<template v-for="(item, index) in optionsObj.ruleStrArr">
<!-- 文本输入框 -->
<template v-if="item.type === 'input'">
<el-input :key="index" v-model="item.value" />
</template>
<!-- 数字输入框 -->
<template v-else-if="item.type === 'number'">
<el-input-number :key="index" v-model="item.value" />
</template>
<!-- 下拉选择框 -->
<template v-else-if="['select', 'multiSelect'].includes(item.type)">
<el-select :key="index" v-model="item.value" :multiple="item.multiple">
<el-option
v-for="option in item.options"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</template>
<!-- 其它类型 -->
<template v-else>{{item.value}}</template>
</template>
基础数据
data() {
return {
// 表单类型数组
formTypeArr: [],
// 需匹配的表单类型数组
needConvertFormTypeArr: ['input', 'number', 'select', 'multiSelect'],
optionsObj: {
ruleStr: '这是一个数字输入框{number},这是文字里的未知项{unknown},这是一个文本输入框{input},这是一个下拉单选框{select},这是一个下拉多选框{multiSelect}',
ruleStrArr: [],
oldFormValue: "[1003, 'unknown', '我是文本', '1', ['1', '2'] ]",
newFormValue: undefined,
oldFormOption: "[[], 'unknown', [], [{'value': '1', 'label': '选项一'}, {'value': '2', 'label': '选项二'}, {'value': '3', 'label': '选项三'}]," +
"[{'value': '1', 'label': '选项一'}, {'value': '2', 'label': '选项二'}, {'value': '3', 'label': '选项三'}]]",
newFormOption: undefined
},
str: '',
formArr: []
}
}
整体实现代码
/**
* 匹配规则数据
* 返回变量类型
* @param {Object} obj
* @param {String} type '1'-匹配字符串,'2'-匹配对象数组
* @returns {String, Array} 变量类型
*/
formatRuleData(obj, type = '1') {
// 转为标准JSON字符串,将'替换为"
obj.newFormValue = obj.oldFormValue.replace(/'/gi, '"')
obj.newFormOption = obj.oldFormOption.replace(/'/gi, '"')
// 转为标准JSON对象
obj.newFormValue = obj.newFormValue ? JSON.parse(obj.newFormValue) : []
obj.newFormOption = obj.newFormOption ? JSON.parse(obj.newFormOption) : []
// 用统一字符替换{}
obj.ruleStrReplace = obj.ruleStr.replace(/{|}/gi, '===')
// 分割obj.ruleStrReplace形成数组以便遍历插值
obj.ruleStrArr = obj.ruleStrReplace.split('===')
// 得到表单组件类型数组
this.formTypeArr = this.matchStr(obj.ruleStr)
// 获取匹配后数据
if (type === '1') {
this.formatStr(obj)
} else {
this.formatObjArr(obj)
}
return type === '1' ? obj.ruleStrArr.join('') : obj.ruleStrArr
}
匹配成值方法
// 去除大括号{}
matchStr(str){
const reg = /{(.*?)}/gi;
const tmpStr = str.match(reg);
return tmpStr.map(item => {
item = item.replace(/{|}/gi, '')
return item
})
},
// 匹配完成填充后字符串
formatStr(obj) {
obj.ruleStrArr = obj.ruleStrArr.map(rule => {
let content = ''
switch (rule) {
// 文本输入、数值输入类型
case 'input':
case 'number':
content = this.formatRichText(obj.newFormValue[0])
break
// 单选类型
case 'select':
content = obj.newFormOption[0].find(item => item.value === obj.newFormValue[0]).label
content = this.formatRichText(content)
break
// 多选类型
case 'multiSelect': {
let text = ''
obj.newFormValue[0].forEach(oldFormValue => {
const value = obj.newFormOption[0].find(item => item.value === oldFormValue).label
text = text ? `${text},${value}` : value
})
content = this.formatRichText(text)
}
break
// 其他类型
default: content = this.formTypeArr.includes(rule) ? `{${rule}}` : rule
}
// 删除已匹配的数值项newFormValue与规则项newFormOption,使得匹配时始终从下标为0的获取无需自增下标
if (this.formTypeArr.includes(rule)) {
obj.newFormOption.shift()
obj.newFormValue.shift()
}
return content
})
},
// 匹配富文本
formatRichText(text) {
return `<span style="color:#3296fa">${text}</span>`
},
匹配成表单项方法
// 匹配对象数组
formatObjArr(obj) {
obj.ruleStrArr = obj.ruleStrArr.map(rule => {
let content = ''
switch (rule) {
// 数值输入、文本输入类型
case 'input':
case 'number':
content = {
type: rule,
value: obj.newFormValue[0]
}
break
// 单选、多选类型
case 'select':
case 'multiSelect':
content = {
type: rule,
multiple: rule === 'multiSelect',
value: obj.newFormValue[0],
options: obj.newFormOption[0]
}
break
// 其他类型
default: {
content = {
type: rule,
value: this.formTypeArr.includes(rule) ? `{${rule}}` : rule
}
}
}
// 删除已匹配的数值项newFormValue与规则项newFormOption,使得匹配时始终从下标为0的获取无需自增下标
if (this.formTypeArr.includes(rule)) {
obj.newFormOption.shift()
obj.newFormValue.shift()
}
return content
})
}
转换为原始格式
// 将表单改变后重新转换为JSON字符串
convertToStr(obj) {
let formValue = []
obj.ruleStrArr.forEach(item => {
if (this.needConvertFormTypeArr.includes(item.type)) {
formValue.push(item.value)
} else if (this.formTypeArr.includes(item.type.replace(/{|}/gi, ''))) {
formValue.push(item.value)
}
})
return JSON.stringify(formValue)
}
以上内容如有纰漏或更优解,望不吝赐教~