88 lines
2.0 KiB
JavaScript
88 lines
2.0 KiB
JavaScript
const lodash = require('lodash')
|
||
|
||
/**
|
||
* 找出 newObj 相对于 oldObj 有差异的部分
|
||
*
|
||
* @param oldObj
|
||
* @param newObj
|
||
* @returns {{}|*}
|
||
*/
|
||
function doDiff (oldObj, newObj) {
|
||
if (newObj == null) {
|
||
return oldObj
|
||
}
|
||
|
||
// 临时的对象,用于找出被删除的数据
|
||
const tempObj = { ...oldObj }
|
||
// 删除空项,使差异对象更干净一些,体现出用户自定义内容
|
||
deleteNullItems(tempObj)
|
||
|
||
// 保存差异的对象
|
||
const diffObj = {}
|
||
|
||
// 读取新对象,并解析
|
||
for (const key in newObj) {
|
||
const newValue = newObj[key]
|
||
const oldValue = oldObj[key]
|
||
|
||
// 新值不为空,旧值为空时,直接取新值
|
||
if (newValue != null && oldValue == null) {
|
||
diffObj[key] = newValue
|
||
continue
|
||
}
|
||
// 新旧值相等时,忽略
|
||
if (lodash.isEqual(newValue, oldValue)) {
|
||
delete tempObj[key]
|
||
continue
|
||
}
|
||
// 新的值为数组时,直接取新值
|
||
if (lodash.isArray(newValue)) {
|
||
diffObj[key] = newValue
|
||
delete tempObj[key]
|
||
continue
|
||
}
|
||
|
||
// 新的值为对象时,递归合并
|
||
if (lodash.isObject(newValue)) {
|
||
diffObj[key] = doDiff(oldValue, newValue)
|
||
delete tempObj[key]
|
||
continue
|
||
}
|
||
|
||
// 基础类型,直接覆盖
|
||
delete tempObj[key]
|
||
diffObj[key] = newValue
|
||
}
|
||
|
||
// tempObj 里面剩下的是被删掉的数据
|
||
lodash.forEach(tempObj, (oldValue, key) => {
|
||
// 将被删除的属性设置为null,目的是为了merge时,将被删掉的对象设置为null,达到删除的目的
|
||
diffObj[key] = null
|
||
})
|
||
|
||
return diffObj
|
||
}
|
||
|
||
function deleteNullItems (target) {
|
||
lodash.forEach(target, (item, key) => {
|
||
if (item == null) {
|
||
delete target[key]
|
||
}
|
||
if (lodash.isObject(item)) {
|
||
deleteNullItems(item)
|
||
}
|
||
})
|
||
}
|
||
|
||
module.exports = {
|
||
doMerge: function (oldObj, newObj) {
|
||
return lodash.mergeWith(oldObj, newObj, function (objValue, srcValue) {
|
||
if (lodash.isArray(objValue)) {
|
||
return srcValue
|
||
}
|
||
})
|
||
},
|
||
doDiff,
|
||
deleteNullItems
|
||
}
|