defineProperty实现数据劫持

202 阅读1分钟

使用Object的defineProperty实现数据劫持功能(vue2数据劫持),一个简单的版本,再次做个记录总结一下。

   const data = {
      name: 'zhm',
      age: 10,
      friend: {
        friendName: '测试'
      },
      colors: ['blue']
    }
    // 变成响应式数据
    let oldArrayProto = Array.prototype
    // 给新对象的__proto__设置为oldArrayProto
    let newArrayProto = Object.create(oldArrayProto)
    let methods = ['push', 'shift', 'unshift', 'pop', 'splice']
    methods.forEach(methodName => {
      newArrayProto[methodName] = function () {
        console.log('视图更新')
        oldArrayProto[methodName].call(this, ...arguments)
      }
    })
    // console.log(oldArrayProto)
    // console.log(newArrayProto)
    // 把数据变成响应式
    observer(data)
    function observer (target) {
      if (typeof target !== 'object' || typeof target === 'null') {
        return target
      }
      for (let key in target) {
        defineReactive(target, key, target[key])
      }
    }
    function defineReactive (target, key, value) {
      // 深度监听
      // console.log(key)
      observer(value)
      if (Array.isArray(target)) {
        target.__proto__ = newArrayProto
      }
      Object.defineProperty(target, key, {
        get () {
          // observer(value)
          return value
        },
        set (newValue) {
          observer(newValue)
          if (newValue !== value) {
            value = newValue
            console.log('视图更新')
          }
        }
      })
    }
    // data.friend.friendName = '不测试'
    // data.age = { num: 10 }
    // data.age.num = 20
    // data.colors.push('blue')