一个网站的渠道网络建设,网站推广建设阶段,黄山市建设工程造价管理站网站,门户网站模板html5在软件研发过程中#xff0c;会遇到很多编辑页面#xff0c;有时编辑页面和新增页面长的基本上一样#xff0c;甚至就是一套页面供新增和编辑共用。编辑页面的场景比较多#xff0c;例如#xff1a;
场景一、字段比较多#xff0c;但实际只修改了几个字段#xff0c;如…在软件研发过程中会遇到很多编辑页面有时编辑页面和新增页面长的基本上一样甚至就是一套页面供新增和编辑共用。编辑页面的场景比较多例如
场景一、字段比较多但实际只修改了几个字段如果把所有字段都回传给后端冗余字段未作变更的字段修改就会有很多而这些未作变更的字段中还有一些字段是后台有翻译和转换的例如金额、类型、状态等如果把这样的字段回传给后台就会造成数据的变更其实不想变更和预期是严重不符的。
场景二、还有一些比较复杂的编辑页面它会有大集合嵌套小集合甚至还有多层嵌套的场景在修改时可能对各个层级的集合又有一些新增、修改、删除的操作。
场景三、场景一和场景二的混合场景。
基于这些复杂的场景如果能够的精确的区分开哪些做了新增、哪些做了变更、哪些删掉了就会让我们的前后端研发小伙伴更轻松的应对这些复杂场景。
接下来我把我对这种复杂场景的处理方案分享出来大家可以参考共同探讨看看还有没有更好的解决方案前端使用的是vue的环境
处理原理 1、进入编辑页面时将查询出来的数据复制成两份一份作为初始数据一份作为修改数据 2、比对初始数据和修改数据的差异新增的、修改的、删除的 3、将差异数据提交给后台后台进行分门别类处理 比对算法
/** * 比较两个对象的差异 * 应用场景编辑页面中表单字段比较多主页面明细页面而修改项很少只需要将修改的字段和必要字段传递给后台就可以不用传递表单中的所有字段默认是传递所有字段 * param {Array/Object} original 原始对象 * param {Array/Object} modified 修改后对象 * param {Array} primaryKeys 主键后台是根据主键修改数据 * param {Array} excludeKeys 过滤字段不参与比较的字段 * return {Object} diffObject 返回有变更的对象字段 */ export function obtainingObjectsDiffrences(original, modified, primaryKeys [id], excludeKeys []) { let diffObject {} // 如果当前为数组先分别区分哪些需要新增、修改、删除 if (typeof original object Array.isArray(original) typeof modified object Array.isArray(modified)) { diffObject subObtainingObjectsDiffrences(original, modified, primaryKeys, excludeKeys) } else if (typeof original object typeof modified object) { // 当前对象字段是否有变更 let levelDiffFlag false // 主键 let primaryKey for (const key in original) { if (!excludeKeys.includes(key)) { if (typeof original[key] object Array.isArray(original[key]) typeof modified[key] object Array.isArray(modified[key])) { const subDiffObject subObtainingObjectsDiffrences(original[key], modified[key], primaryKeys, excludeKeys) if (Object.keys(subDiffObject).length ! 0) { diffObject[key] subDiffObject.modifiedArray diffObject[key New] subDiffObject.newArray diffObject[key Removed] subDiffObject.removedArray } } else if (typeof original[key] object typeof modified[key] object) { const subDiffObject obtainingObjectsDiffrences(original[key], modified[key], primaryKeys, excludeKeys) if (Object.keys(subDiffObject).length ! 0) { diffObject[key] subDiffObject } } else if (original[key] ! modified[key]) { // 更新modifiedData对象中的属性值 diffObject[key] modified[key] levelDiffFlag true } } if (primaryKeys.includes(key)) { primaryKey key } } // 设置主键字段值 if (levelDiffFlag primaryKey ! undefined) { diffObject[primaryKey] original[primaryKey] } } return diffObject }
/** * 比对数组之间的差异新增、修改、删除 * param {Array} original 原始数组 * param {Array} modified 修改后的数组 * param {Array} primaryKeys 主键列表 * param {Array} excludeKeys 不参与比对的字段 * return {Object} diffObject 返回有差异的数组 */ function subObtainingObjectsDiffrences(original, modified, primaryKeys, excludeKeys) { const diffObject {} // 子列表主键 let subPrimaryKey for (const key in original[0]) { if (primaryKeys.includes(key)) { subPrimaryKey key } } // 具有相同主键的初始列表 const commonOrignal original.filter(itemA modified.some(itemB itemA[subPrimaryKey] itemB[subPrimaryKey])) // 具有相同主键的修改列表 const commonModified modified.filter(itemA original.some(itemB itemA[subPrimaryKey] itemB[subPrimaryKey])) // 删除列表 const removedArray original.filter(itemA !modified.some(itemB itemA[subPrimaryKey] itemB[subPrimaryKey])) if (removedArray.length ! 0) { diffObject.removedArray removedArray } // 新增列表 const newArray modified.filter(itemA !original.some(itemB itemA[subPrimaryKey] itemB[subPrimaryKey])) if (newArray.length ! 0) { diffObject.newArray newArray } // 修改条目如果属性值是对象则递归调用obtainingObjectsDiffrences进行比较 const modifiedArray [] commonOrignal.forEach(subOrignal { const subModified commonModified.filter(item item[subPrimaryKey] subOrignal[subPrimaryKey])[0] const subModifiedObject obtainingObjectsDiffrences(subOrignal, subModified, primaryKeys, excludeKeys) if (Object.keys(subModifiedObject).length ! 0) { modifiedArray.push(subModifiedObject) } }) if (modifiedArray.length ! 0) { diffObject.modifiedArray modifiedArray } return diffObject } 调用示例
const originalUserList [{ userId: a1, username: tom, password: 123456, remarks: asdfasdfadsf, roles: [{ roleId: r1, roleName: 管理员, remarks: asdfasdfadsf, menus: [{ menuId: m1, menuName: 用户管理, remarks: asdfasdfadsf }, { menuId: m2, menuName: 角色管理, remarks: asdfasdfadsf }, { menuId: m3, menuName: 菜单管理, remarks: asdfasdfadsf }] }] }, { userId: a2, username: cat, password: 123456, remarks: asdfasdfadsf, roles: [{ roleId: r1, roleName: 管理员, remarks: asdfasdfadsf, menus: [{ menuId: m1, menuName: 用户管理, remarks: asdfasdfadsf }, { menuId: m2, menuName: 角色管理, remarks: asdfasdfadsf }, { menuId: m3, menuName: 菜单管理, remarks: asdfasdfadsf }] }] }] const modifiedUserList [{ userId: a1, username: tom, password: 123456789, remarks: asdf, roles: [{ roleId: r1, roleName: 管理员, remarks: asdf, menus: [{ menuId: m1, menuName: 企业管理, remarks: asdf }, { menuId: m3, menuName: 菜单管理, remarks: asdf }] }] }, { userId: a3, username: tom1, password: 12345686, remarks: asdfasdfadsf, roles: [{ roleId: r1, roleName: 管理员, remarks: asdfasdfadsf, menus: [{ menuId: m1, menuName: 用户管理, remarks: asdfasdfadsf }, { menuId: m2, menuName: 角色管理, remarks: asdfasdfadsf }, { menuId: m3, menuName: 菜单管理, remarks: asdfasdfadsf }] }] }] const diff obtainingObjectsDiffrences(originalUserList, modifiedUserList, [userId, roleId, menuId], [remarks]) console.log(原始列表, originalUserList) console.log(修改列表, modifiedUserList) console.log(差异列表, diff) 调用结果 结语
1、对于比较差异的返回字段的命名前后端小伙伴可以商量着来
2、如果后端的新增保存方法是saveOrUpdate的通用方法前端可以把对应的新增列表和修改列表合并了
3、如果后端的删除是removeByIds的方法前端可以把返回的removeArray再按照主键过滤一下
4、注意2和3是要后端统一进行事务处理的不要前端单独调用后端新增的、修改的、删除的方法 这是我的处理方案供参考如果有更有方案可以一起探讨