vue3源码学习(一)简单的响应式

一、分析

两个关键词,ProxyReflect

1. Proxy

使用Proxy代理一个对象时,会返回一个代理值。读取代理值的属性时会触发get函数,修改代理值的属性时会触发set函数。

例子如下:

  • 创建了一个响应式对象person
  • 读取person.name时,触发 get 函数,控制台打印读取->name
  • 修改person.name时,触发 set 函数,控制台打印修改->name->李四
const person = new Proxy(
  { name: '张三' },
  {
    get(target, prop) {
      console.log(`读取->${prop}`)
      return target[prop]
    },
    set(target, prop, value) {
      console.log(`修改->${prop}->${value}`)
      target[prop] = value
    },
  }
)
person.name // 读取
person.name = '李四' // 修改

// 控制台打印
// 读取->name
// 修改->name->李四

2. Reflect

Reflect的作用是调用对象的基本操作(内部方法),详情参考 MDN

const obj = { a: 1 }

obj.a // 1
Reflect.get(obj, 'a') //1

obj.a = 2 //2
Reflect.set(obj, 'a', 2) //2

从结果上看,执行 obj.aReflect.get(obj, 'a')一样;执行obj.a = 2Reflect.set(obj, 'a',2)一样。那他们的区别是什么?

区别一

执行 obj.a 实际上等于执行
------------------------------------------------------------------
xxx
xxx
Reflect.get(obj, 'a')
xxx
xxx
------------------------------------------------------------------
也就是说 Reflect.get(obj, 'a') 是执行 obj.a 中的某一个步骤,
同理 Reflect.set(obj, 'a',2) 是执行 obj.a = 2 中的某一个步骤

如果我们不需要其他步骤,那么就可以使用 Reflect 来跳过这些步骤

区别二

Reflect.get(target, propertyKey[, receiver])
Reflect.set(target, propertyKey, value[, receiver])
可以接收一个receiver参数,用来改变this的指向

const obj = {
  a: 1,
  b: 2,
  get c() {
    return this.a + this.b
  },
}

console.log(obj.c) // 3
console.log(Reflect.get(obj, 'c')) //3
console.log(Reflect.get(obj, 'c', { a: 3, b: 4 })) //7

二、实现

/**
 *  创建一个响应式对象
 * @param {Object} obj
 */
function reactive(obj) {
  const proxy = new Proxy(obj, {
    get(target, prop) {
      console.log(`读取->${prop}`)
      return Reflect.get(target, prop, proxy) // 是调用 Reflect 将对象中的 this 指向代理
    },
    set(target, prop, value) {
      console.log(`修改->${prop}->${value}`)
      Reflect.set(target, prop, value, proxy)
    },
  })
  return proxy
}

// 使用示例
const person = reactive({
  name: '张三',
  age: 18,
  get info() {
    return this.name + '-' + this.age
  },
})
console.log(person.name)
console.log(person.age)
console.log(person.info)

person.name = '李四'
person.age = 20

console.log(person.name)
console.log(person.age)
console.log(person.info)
控制台打印
读取->name
张三
读取->age
18
读取->info
读取->name
读取->age
张三-18
修改->name->李四
修改->age->20
读取->name
李四
读取->age
20
读取->info
读取->name
读取->age
李四-20

三、结合html

原文链接:https://juejin.cn/post/7352079398071943231 作者:_Xyuan

(0)
上一篇 2024年3月31日 上午10:43
下一篇 2024年3月31日 上午10:54

相关推荐

发表回复

登录后才能评论