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的对比 🤓
为啥还要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
对象中指定了getter
,receiver
则为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