因为开发需要,要将前后端交互参数 json 对象扁平化处理,于是抽象了一个工具函数。
实现方法参考了
https://segmentfault.com/q/1010000007039588
参考方法
export function jsonFlatten(data) {
var result = {}
function recurse(cur, prop) {
if (Object(cur) !== cur) {
result[prop] = cur
} else if (Array.isArray(cur)) {
for (var i = 0, l = cur.length; i < l; i++) { recurse(cur[i], prop + '[' + i + ']') }
if (l === 0) { result[prop] = [] }
} else {
var isEmpty = true
for (var p in cur) {
isEmpty = false
recurse(cur[p], prop ? prop + '.' + p : p)
}
if (isEmpty && prop) { result[prop] = {} }
}
}
recurse(data, '')
return result
}
页面打印
总结:该方法拉平了对象,同时保留了层级和所属关系,应该是为了回溯回去。
因为不符合开发需求,所以修改了下。
改动地方:recurse(cur[p], prop ? prop + '.' + p : p) 改为 recurse(cur[p], p)
修改后方法
实现如下:
export function jsonFlatten(data) {
var result = {}
function recurse(cur, prop) {
if (Object(cur) !== cur) {
result[prop] = cur
} else if (Array.isArray(cur)) {
for (var i = 0, l = cur.length; i < l; i++) { recurse(cur[i], prop + '[' + i + ']') }
if (l === 0) { result[prop] = [] }
} else {
var isEmpty = true
for (var p in cur) {
isEmpty = false
recurse(cur[p], p)
}
if (isEmpty && prop) { result[prop] = {} }
}
}
recurse(data, '')
return result
}
页面应用
handleSubmit() {
this.userForm.roleId = this.userForm.roles[0].id
console.log(this.userForm)
const data = jsonFlatten(this.userForm)
console.log(data)
if (this.dialogType === 'edit') {
this.updateUser(data)
} else {
this.addUser(data)
}
},
打印
总结:方法完全拉平了对象。
不过需要注意,json 对象中的数组元素命名,不要和外面的键名重复了。
如:roles[0].id 还是改为 roles[0].roleId 比较安全,避免同名覆盖。例子中 info 对象中的 id 覆盖了 roles 数组中的 id。
最佳实践
提前处理数据
在表单回显数据前,先处理好表单数据,而不是在最后提交表单前修改。
handleEdit(scope) {
this.dialogType = 'edit'
this.dialogVisible = true
var res = deepClone(scope.row)
// 处理用户的角色数组为空的情况
if (res.roles.length === 0) {
res.roles.push({
roleId: '',
roleName: ''
})
} else {
res.roleId = res.roles[0].id
res.roleName = res.roles[0].name
}
// 提前拉平对象
this.userForm = jsonFlatten(res)
},
handleSubmit() {
if (this.dialogType === 'edit') {
this.updateUser(this.userForm)
} else {
this.addUser(this.userForm)
}
},
因为表单校验
userFormRules: {
username: [{ required: true, trigger: 'blur', message: '账户名称不能为空' }],
password: [{ required: true, trigger: 'blur', message: '密码不能为空' }],
confirmPwd: [{ required: true, trigger: 'blur', validator: validateConfirmPwd }]
}
好像不能识别嵌套对象
<el-form-item label="账户名称" prop="username">
<el-input v-model="userForm.info.username" />
</el-form-item>
另外,嵌套对象在回显数据时,需要初始化数据内部每个属性,不像一层的对象,写个{}空对象即可。
defaultUser: {
id: '',
roleId: '',
roleName: '',
username: '',
password: '',
confirmPwd: '',
photo: '',
phone: '',
email: '',
sex: '',
status: 0,
brief: ''
},
userForm: {},
对比
memberForm: { // 多层嵌套的对象表单需要初始值
info: {
realName: '',
idCard: '',
photo: ''
},
roles: []
},