手写简单的响应式原理(包含vue2、vue3)

// 要实现的效果: 当obj、info中的属性发生改变时,用到对应属性的函数都会再调用
const obj = {
  name: 'zerus',
  age: 18,
  height: 160,
  movies: ['不能说的秘密', '大灌篮', '头文字D'],
}

const info = {
  province: '广东省',
  address: '深圳市',
  subInfo: {
    address: '火星',
  }
}

let activeReactiveFn = null
const reactiveMap = new WeakMap()

class Depend {
  constructor() {
    this.reactiveFns = new Set()
  }
  depend() {
    if (activeReactiveFn) {
      this.reactiveFns.add(activeReactiveFn)
    }
  }
  notify() {
    this.reactiveFns.forEach(fn => fn())
  }
}

function getDepend(target, key) {
  let map = reactiveMap.get(target)
  if (!map) {
    map = new Map()
    reactiveMap.set(target, map)
  }
  let depend = map.get(key)
  if (!depend) {
    depend = new Depend()
    map.set(key, depend)
  }
  return depend
}

function reactive(obj) {
  return new Proxy(obj, {
    get: function (target, key, receiver) {
      console.log(target, key)
      const depend = getDepend(target, key)
      depend.depend()
      return Reflect.get(target, key, receiver)
    },
    set: function (target, key, newValue, receiver) {
      const depend = getDepend(target, key)
      Reflect.set(target, key, newValue, receiver)
      depend.notify()
    },
    deleteProperty(target, key) {
      const depend = getDepend(target, key)
      Reflect.deleteProperty(target, key)
      depend.notify()
    }
  })
}

function watchFn(fn) {
  activeReactiveFn = fn
  fn()
  activeReactiveFn = null
}

const objProxy = reactive(obj)
const infoProxy = reactive(info)

watchFn(function () {
  console.log(objProxy.name, '-----obj.name --- 1')
  console.log(objProxy.name, '-----obj.name --- 2')
})

watchFn(function () {
  console.log(infoProxy.address, '-----info.address --- ')
})

objProxy.name = '大帅哥'
infoProxy.address = '北京市'

delete objProxy.name

watchFn(function () {
  console.log(objProxy.xxx, '-----objProxy.xxx --- ')
})

objProxy.xxx = '新的属性xxx'
objProxy.xxx = '和人呵呵呵呵'



Vue2的响应式原理也很简单,把reactive部分用Object.defindedProptery实现就好了

// 使普通的对象变成响应式对象
function reactive(obj) {
  Object.keys(obj).forEach(key => {
    let value = obj[key]
    Object.defineProperty(obj, key, {
      get: function () {
        const depend = getDepend(obj, key)
        depend.depend()
        return value
      },
      set: function (newValue) {
        const depend = getDepend(obj, key)
        value = newValue
        depend.notify()
      }
    })
  })
  return obj
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值