import isEqual from 'lodash.isequal'
/**
* 对比两个对象,计算他们不同的部分
* create update remove
* { 'a.b': { type: 'create/update/remove', before: '', after: '' } }
* deep - 是否深层次对比
*/
export default function diffObject(
before = {},
after = {},
deep,
ret,
keyPrefix = ''
) {
if (!ret) {
ret = {
create: {},
update: {},
remove: {}
}
}
// create
let keys = []
for (let p in after) {
if (!before.hasOwnProperty(p) && after.hasOwnProperty(p)) {
keys.push(p)
}
}
if (keys.length) {
merge(ret.create, keys, 'create')
}
// remove
keys = []
for (let p in before) {
if (!after.hasOwnProperty(p) && before.hasOwnProperty(p)) {
keys.push(p)
}
}
if (keys.length) {
merge(ret.remove, keys, 'remove')
}
// update
keys = []
for (let p in after) {
if (!before.hasOwnProperty(p) || !after.hasOwnProperty(p)) {
continue
}
if (deep && isObject(after[p]) && isObject(before[p])) {
diffObject(before[p], after[p], deep, ret, keyPrefix + p + '.')
continue
}
if (!isEqual(after[p], before[p])) {
keys.push(p)
}
}
if (keys.length) {
merge(ret.update, keys, 'update')
}
function merge(target, keys, type) {
for (let i = 0; i < keys.length; i++) {
let key = keys[i]
target[keyPrefix + key] = {
type,
before: before[key],
after: after[key]
}
}
}
return ret
}
export function diffObjectAll(before, after, deep) {
const ret = diffObject(before, after, deep)
ret.all = Object.assign({}, ret.create, ret.update, ret.remove)
return ret
}
function isObject(val) {
return Object.prototype.toString.call(val) === '[object Object]'
}
// function isEmpty(val) {
// return val === undefined || val === null || val === ''
// }
import diffObject, { diffObjectAll } from './diffObject'
test('lang.diffObject', () => {
const before = {
a: 1,
b: 2,
c: 3,
d: {
x: 1,
y: 2
}
}
const after = {
a: 1,
b: 3,
d: {
x: 5,
y: 7
},
e: 9
}
expect(diffObject(before, after)).toEqual({
create: {
e: {
type: 'create',
before: undefined,
after: 9
}
},
remove: {
c: {
type: 'remove',
before: 3,
after: undefined
}
},
update: {
b: {
type: 'update',
before: 2,
after: 3
},
d: {
type: 'update',
before: {
x: 1,
y: 2
},
after: {
x: 5,
y: 7
}
}
}
})
expect(diffObject(before, after, true)).toEqual({
create: {
e: {
type: 'create',
before: undefined,
after: 9
}
},
remove: {
c: {
type: 'remove',
before: 3,
after: undefined
}
},
update: {
b: {
type: 'update',
before: 2,
after: 3
},
'd.x': {
type: 'update',
before: 1,
after: 5
},
'd.y': {
type: 'update',
before: 2,
after: 7
}
}
})
const diffAll = diffObjectAll(before, after)
expect(diffAll.all).toBeTruthy()
})
网友评论