加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

茶余饭后聊聊 Vue3.0 响应式数据那些事儿

发布时间:2019-10-31 12:00:23 所属栏目:建站 来源:佚名
导读:别再更新了,实在是学不动了这句话道出了多少前端开发者的心声,不幸的是 Vue 的作者在国庆区间发布了 Vue3.0 的 pre-Aplha 版本,这意味着 Vue3.0 快要和我们见面了。既来之则安之,扶我起来我要开始讲了。Vue3.0 为了达到更快、更

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 试试水

  1. let map = new Map([["name","zhengcaiyun"]]) 
  2. let mapProxy = new Proxy(map, { 
  3.   get(target, key, receiver) { 
  4.     console.log("取值:",key) 
  5.     return Reflect.get(target, key, receiver) 
  6.   } 
  7. }) 
  8. mapProxy.get("name") 
  1. Uncaught TypeError: Method Map.prototype.get called on incompatible receiver [object Object] 

一盆凉水泼来,报错了。原来 Map、Set 对象赋值、取值和他们内部的 this 指向有关系,但这里的 this 指向的是其实是 Proxy 对象,所以得这样干

  1. let map = new Map([['name','wangyangyang']]) 
  2. let mapProxy = new Proxy(map, { 
  3.   get(target, key, receiver) { 
  4.     var value = Reflect.get(...arguments) 
  5.      console.log("取值:",...arguments) 
  6.     return typeof value == 'function' ? value.bind(target) : value 
  7.   } 
  8. }) 
  9. mapProxy.get("name") 

当获取的是一个函数的时候,通过作用域绑定的方式将原对象绑定到 Map、Set 对象上就好了。

Vue3.0 是如何实现集合类型数据监听的?

眼尖的同学看完上面这段代码会发现一个问题,集合是没有 set 方法,集合赋值用的是 add 操作,那咋办呢?来看看那么 Vue3.0 是怎么处理的,上一段简化后的源码

  1. function reactive(target: object) { 
  2.   return createReactiveObject( 
  3.     target, 
  4.     rawToReactive, 
  5.     reactiveToRaw, 
  6.     mutableHandlers, 
  7.     mutableCollectionHandlers 
  8.   ) 
  9.  
  10. function createReactiveObject( 
  11.   target: any, 
  12.   toProxy: WeakMap<any, any>, 
  13.   toRaw: WeakMap<any, any>, 
  14.   baseHandlers: ProxyHandler<any>, 
  15.   collectionHandlers: ProxyHandler<any> 
  16. ) { 
  17.   //collectionTypes = new Set<Function>([Set, Map, WeakMap, WeakSet]) 
  18.   const handlers = collectionTypes.has(target.constructor) 
  19.     ? collectionHandlers 
  20.     : baseHandlers 
  21.   //生成代理对象 
  22.   observed = new Proxy(target, handlers) 
  23.   toProxy.set(target, observed) 
  24.   toRaw.set(observed, target) 
  25.   if (!targetMap.has(target)) { 
  26.     targetMap.set(target, new Map()) 
  27.   } 
  28.   return observed 

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读