公司项目中有一个需求,要求对比两次填写表单时的差异,表单内容有对象,有数组,因此写了个diff.js,直接贴代码
/**
* 找到两个相同结构的对象的差异内容,并返回包含所有差异的数组
* 注意对象内的值只能是简单类型,复杂类型不考虑
* @param origin 原对象
* @param current 可能修改过的对象
* @param arrayKey 数组中需要对比的主键
*/
export function diff(origin, current, arrayKey) {
let diff = {}
let log
for (var key in origin) {
if (typeof origin[key] === 'object' && typeof current[key] && origin[key] && current[key]) {
if (origin[key] instanceof Array && current[key] instanceof Array) {
log = diffArray(origin[key], current[key], arrayKey)
} else {
log = diffObject(origin[key], current[key])
}
if (Object.keys(log).length > 0) {
diff[key] = log
}
} else if (origin[key] !== current[key]) {
diff[key] = {
origin: origin[key],
current: current[key]
}
}
}
if (JSON.stringify(diff) == '{}') {
return null
} else {
return diff
}
}
/**
* 找到两个相同结构的对象的差异内容,并返回包含所有差异的数组
* 注意对象内的值只能是简单类型,复杂类型不考虑
* @param originObj 原对象
* @param currentObj 可能修改过的对象
* @returns {{}} 包含所有差异的数组
*/
function diffObject(originObj, currentObj) {
const resultObj = {};
// 遍历originObj的键数组,因为originObj和currentObj结构相同,所以不考虑结构上的差异
Object.keys(originObj).forEach(key => {
if (originObj[key] !== currentObj[key]) {
// 将变化过的属性挂载到返回对象中
resultObj[key] = {
origin: originObj[key],
current: currentObj[key]
}
// resultObj[key] = currentObj[key];
}
});
if (JSON.stringify(resultObj) == '{}') {
return false
} else {
return resultObj
}
}
/**
* 找到两个对象数组的差异,并打印从originList到currentList的所有变化
* 注意约定id不能修改
* @param originList 原数组
* @param currentList 可能修改过的数组
* @param keyName 子元素主键
*/
function diffArray(originList, currentList, keyName) {
let logArr = []
let originListIds = originList.map(v => v[keyName])
let currentListIds = currentList.map(v => v[keyName])
originList.forEach((originObj) => {
let index = currentListIds.indexOf(originObj[keyName])
if (index >= 0) {
let tempLog = diffObject(originList[index], currentList[index])
// 原对象主键在现对象主键中
if (tempLog) {
// 如果templog有值,表示修改更新
let log = {
id: originObj[keyName],
operate: 'modify',
log: tempLog
}
logArr.push(log)
}
} else {
// 原对象主键不在现对象主键中,表示原对象已被删除
let log = {
id: originObj[keyName],
operate: 'delete',
log: originObj
}
logArr.push(log)
}
})
currentList.forEach((currentObj) => {
// 查询新列表中的子元素主键是否存在于旧列表之中
let index = originListIds.indexOf(currentObj[keyName])
// 不存在则为新增
if (index < 0) {
let log = {
id: currentObj[keyName],
operate: 'add',
log: currentObj
}
logArr.push(log)
}
})
return logArr
}
用法
let orgin = { a: '1', b: '2', c: { temp1: 'aaa', temp2: 'bbb' }, d: [{ id: '111', text: 'asd' }, { id: '222', text: 'asdsa' }] }
let current = { a: '1', b: '45', c: { temp1: 'aaa', temp3: 'ccc' }, d: [{ id: '111', text: 'asd' }, { id: '333', text: 'xswedc' }] }
console.log(diff(orgin, current, 'id'))
网友评论