diffObj

作者: lessonSam | 来源:发表于2020-08-11 16:19 被阅读0次
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()
})

相关文章

网友评论

      本文标题:diffObj

      本文链接:https://www.haomeiwen.com/subject/vqjydktx.html