You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// package/reactivity/src/reactive.tsfunctioncreateReactiveObject(target: Target,isReadonly: boolean,baseHandlers: ProxyHandler<any>,collectionHandlers: ProxyHandler<any>,proxyMap: WeakMap<Target,any>){if(!isObject(target)){if(__DEV__){console.warn(`value cannot be made reactive: ${String(target)}`);}returntarget;}// target is already a Proxy, return it.// exception: calling readonly() on a reactive objectif(target[ReactiveFlags.RAW]&&!(isReadonly&&target[ReactiveFlags.IS_REACTIVE])){returntarget;}// target already has corresponding ProxyconstexistingProxy=proxyMap.get(target);if(existingProxy){returnexistingProxy;}// only a whitelist of value types can be observed.consttargetType=getTargetType(target);if(targetType===TargetType.INVALID){returntarget;}constproxy=newProxy(target,targetType===TargetType.COLLECTION ? collectionHandlers : baseHandlers);proxyMap.set(target,proxy);returnproxy;}
正文开始...
vue2 源码中的数据劫持
我们会发现其实在
vue2
源码中,本质上就是利用Object.defineProperty
来劫持对象。每劫持一组对象,首先会实例化一个
Dep
对象,每个拦截的对象属性都会动态添加get
和set
将传入的data
或者prop
变成响应式,在Object.defineProperty
的get
中,当我们访问对象的某个属性时,就会先调用get
方法,依赖收集调用dep.depend()
,当我们设置该属性值时就会调用set
方法调用dep.notify()``派发更新
所有的数据,在调用notify
时会调用实例Watch
的run
,从而执行watch
的回调方法。在
vue2
源码中劫持对象实现数据驱动视图,那么我们依葫芦画瓢,化繁为简,实现一个自己的数据劫持吧。新建一个
index.js
再新建一个
html
引入index.js
直接打开
index.html
当我们大开控制台时,我们直接修改
options.age = 10
此时会触发拦截器的set
方法,从而进行更新页面数据操作。在源码里里面处理是相当复杂的,我们可以看到访问数据时,会先调用
get
方法,在dep.depend()
进行依赖收集,然后再设置对象的值时,会调用set
方法,派发更新操作。更多关于vue2
响应式原理可以参考这篇文章响应式原理vue3 是如何做数据劫持的
vue3
主要利用Proxy
这个API
来实现对象劫持的,关于Proxy
可以看下阮一峰老师的 es6 教程proxy,全网讲解Proxy
最好的教程了。继续用个例子来感受下
当我们在控制输入
proxy.name = 111
时,此时就会触发new Proxy()
内部的set
方法,而我们此时采用的是利用Reflect.set(target,key,val)
成功的设置了,在get
中,我们时用Relect.get(target, key)
获取对应的属性值。这点与
vue2
中劫持数据的方式比较大,具体可以看下vue3
源码响应式reactive
实现从源码中我们可以看出在
vue3
使用reative
初始化响应式数据时,实际上它就是就是一个被proxy
代理后的数据,并且使用WeakMap
来存储响应式数据的。相比较
vue2
的defineProperty
,vue3
的Proxy
更加强大,因为代理对象对劫持的对象动态新增属性也一样有检测,而defineProperty
就没有这种特性,它只能劫持已有的对象属性。总结
在
vue2
中数据劫持是用Object.defineProperty
,当访问对象属性时会触发get
方法进行依赖收集,当设置对象属性时会触发set
方法进行派发更新操作。在
vue3
中数据劫持时用new Proxy()
来做的,可以动态的监测对象的属性新增与删除操作,效率高,实用简单。本文示例code example
The text was updated successfully, but these errors were encountered: