vue3.0-响应式原理-Proxy

1:什么是响应式❓

例子:let a = 1,b = 2;let c = a + b

conosle.log(c)  // => 3

这个时候需要触发c 返回 结果

改变 a 的值 再次打印c 才会显示结果

响应式就是改变a的值,c就会自动改变结果

2:js中如何实现响应式❓

  • 检测其中某一个值是否发生变化
  • 用跟踪(track)函数修改值
  • 用触发(trigger)函数更新为最新的值

 

3:Vue是怎么实现响应式的?vue中如何跟踪变化❓

vue中会用Object.defineProperty 的set,get方法处理遍历所有的property并将其转换为Proxy

为啥用Proxy?之前的不好吗?

两者的Surface Api 相同,但是Proxy 更简单,同时提升了性能,代码简单它不香吗?

 

提升了那些性能❓简单了啥❓

Proxy 与 Object.defineProperty的对比  🤓

关于ES6代理性能的思考 🤓

 

为啥还要defineProperty,不直接用Proxy❓

为了支持IE浏览器!!

 

Proxy 到底是啥❓

Proxy 是一个包含另一个对象或函数并允许你对其进行拦截的对象。 (vue官方说法)
或者就叫代理Proxy对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。(mdn说法)

 1 const dinner = {
 2   meal: 'tacos'
 3 }
 4 
 5 const handler = {
 6   get(target, prop) { // target源对象 prop 对象的key
 7     // 这里可以插一个拦截器
 8     return target[prop] // 返回对应的value
 9   }
10 }
11 
12 const proxy = new Proxy(dinner, handler)
13 console.log(proxy.meal)
14 
15 // tacos

 

 

Proxy提供了一个特性,不必这样的返回target[prop],而是进一步使用Reflect方法。它允许我们正确的执行this绑定,比如

const dinner = {
  meal: 'tacos'
}

const handler = {
  get(target, prop, receiver) {
    // ...arguments  => {meal: "tacos"} "meal" Proxy {meal: "tacos"}
    return Reflect.get(...arguments)
  }
}

const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)  // tacos
console.log(proxy)  // Proxy {meal: "tacos"}

 

 

Reflect.get是啥❓

Reflect  是一个内置对象,它提供了拦截js 操作的方法
Reflect.get 获取对象身上某个属性的值,类似于 target[name]

 

Reflect.get(target, propertyKey[, receiver])

target需要取值的目标对象

propertyKey需要获取的值的键值

receiver如果target对象中指定了getterreceiver则为getter调用时的this值。

我们之前提到过,为了有一个 API 能够在某些内容发生变化时更新最终值,我们必须在内容发生变化时设置新的值。我们在处理器,一个名为 track 的函数中执行此操作,该函数可以传入 target 和 key 两个参数。

const dinner = {
  meal: 'tacos'
}

const handler = {
  get(target, prop, receiver) {
    track(target, prop) // 这个玩意就是上面提到的 用跟踪(track)函数修改值
    return Reflect.get(...arguments)
  }
}

const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)

// tacos

 

 

现在跟踪函数也好了,该触发(trigger)函数了

当某些内容发生改变时我们会设置新的值。为此,我们将通过触发这些更改来设置新 Proxy 的更改:

const dinner = {
  meal: 'tacos'
}

const handler = {
  get(target, prop, receiver) {
    track(target, prop) // 跟踪 key修改了值
    return Reflect.get(...arguments)
  },
  set(target, key, value, receiver) {
    trigger(target, key) // 触发了,去改 key 的value
    return Reflect.set(...arguments)
  }
}

const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)

// tacos

 

 

现在回头看看

js中如何实现响应式的❓

  • 检测其中某一个值是否发生变化
  • 用跟踪(track)函数修改值
  • 用触发(trigger)函数更新为最新的值

Vue就是这么干的

  • 当某个值发生变化时进行检测:我们不再需要这样做,因为 Proxy 允许我们拦截它
  • 跟踪更改它的函数:我们在 Proxy 中的 getter 中执行此操作,称为 effect
  • 触发函数以便它可以更新最终值:我们在 Proxy 中的 setter 中进行该操作,名为 trigger
posted @ 2021-02-24 16:39  懒人的懒  阅读(866)  评论(0编辑  收藏  举报