| 
                         Vue3.0 以前组件实例在初始化的时候会将 data 整个对象变为可观察对象,通过递归的方式给每个 Key  使用Object.defineProperty 加上 getter 和 settter,如果是数组就重写代理数组对象的七个方法。而在 Vue3.0  中,将可响应式对象创建的权利交给了开发者,开发者可以通过暴露的 reactive, compted, effect  方法自定义自己需要响应式能力的数据,实例在初始化时不需要再去递归 data 对象了,从而降低了组件实例化的时间。 
Vue3.0 以前生成响应式对象会对对象进行深度遍历,同时为每个 Key 生成一个 def 对象用来保存 Key 的所有依赖项,当 Key 对应的  Value 变化的时候通知依赖项进行 update。但如果这些依赖项在页面整个生命周期内不需要更新的时候,这时 def  对象收集的依赖项不仅没用而且还会占用内存,如果可以在初始化 data 的时候忽略掉这些不会变化的值就好了。Vue3.0 通过暴露的 reactive  方法,开发者可以选择性的创建可观察对象,达到减少依赖项的保存,降低了运行内存的使用。 
    - Map、Set、WeakSet、WeakMap的监听
 
 
前面提到 Proxy 可以代理所有的对象,立马联想到了 ES6 里面新增的集合 Map、Set, 聚合类型的支持得益于 Proxy 和  Reflect。讲真的这之前还真不知道 Proxy 这么刚啥都能代理,二话不说直接动手用 Proxy 代理了一个 map 试试水 
- let map = new Map([["name","zhengcaiyun"]]) 
 - let mapProxy = new Proxy(map, { 
 -   get(target, key, receiver) { 
 -     console.log("取值:",key) 
 -     return Reflect.get(target, key, receiver) 
 -   } 
 - }) 
 - mapProxy.get("name") 
 
  
- Uncaught TypeError: Method Map.prototype.get called on incompatible receiver [object Object] 
 
  
一盆凉水泼来,报错了。原来 Map、Set 对象赋值、取值和他们内部的 this 指向有关系,但这里的 this 指向的是其实是 Proxy  对象,所以得这样干 
- let map = new Map([['name','wangyangyang']]) 
 - let mapProxy = new Proxy(map, { 
 -   get(target, key, receiver) { 
 -     var value = Reflect.get(...arguments) 
 -      console.log("取值:",...arguments) 
 -     return typeof value == 'function' ? value.bind(target) : value 
 -   } 
 - }) 
 - mapProxy.get("name") 
 
  
当获取的是一个函数的时候,通过作用域绑定的方式将原对象绑定到 Map、Set 对象上就好了。 
Vue3.0 是如何实现集合类型数据监听的? 
眼尖的同学看完上面这段代码会发现一个问题,集合是没有 set 方法,集合赋值用的是 add 操作,那咋办呢?来看看那么 Vue3.0  是怎么处理的,上一段简化后的源码 
- function reactive(target: object) { 
 -   return createReactiveObject( 
 -     target, 
 -     rawToReactive, 
 -     reactiveToRaw, 
 -     mutableHandlers, 
 -     mutableCollectionHandlers 
 -   ) 
 - } 
 -  
 - function createReactiveObject( 
 -   target: any, 
 -   toProxy: WeakMap<any, any>, 
 -   toRaw: WeakMap<any, any>, 
 -   baseHandlers: ProxyHandler<any>, 
 -   collectionHandlers: ProxyHandler<any> 
 - ) { 
 -   //collectionTypes = new Set<Function>([Set, Map, WeakMap, WeakSet]) 
 -   const handlers = collectionTypes.has(target.constructor) 
 -     ? collectionHandlers 
 -     : baseHandlers 
 -   //生成代理对象 
 -   observed = new Proxy(target, handlers) 
 -   toProxy.set(target, observed) 
 -   toRaw.set(observed, target) 
 -   if (!targetMap.has(target)) { 
 -     targetMap.set(target, new Map()) 
 -   } 
 -   return observed 
 - } 
 
                          (编辑:91站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |