vue2.x 版本中 Object.defineProperty 对象属性监听和关联
前言
在 vue2.x 版本官方文档中深入响应式原理 https://cn.vuejs.org/v2/guide/reactivity.html一文的解释当中,Object.defineProperty 将声明响应式 property 数据的状态转换为 getter 和 setter。
Object.defineProperty 基本使用和概念
官方解释的概念是
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
Object.defineProperty 新增对象属性
当 enumerable 设置为 false 的时候,我们通过 Object.keys 枚举属性,并不能获取到 name 属性
使用 Object.defineProperty 修改和监听属性值的变化
通过 get 和 set 操作对象属性类似于我们在 vue 开发过程中的计算属性computed详解,通过 get 和 set 对当前对象进行设置属性值
Object.defineProperty 小结
由上面的的例子我们可以知道,当我们使用 Object.defineProperty 操作对象的时候,都是直接通过对象属性进行操作,而不是对整个对象进行修改,删除和新增,查询属性
在使用 Object.defineProperty 方法操作的时候,一些默认的属性选项,需要我们注意
Object.defineProperty 和 vue2.x 的联系
回到开头提到的官方文档中描述的,响应式原理中,如下图
图片源自 vue 官方文档深入响应式原理: https://cn.vuejs.org/v2/guide/reactivity.html
当组件渲染时,通过对象劫持,遍历 data 状态,那么需要考虑的点是:
假如在组件运行时,我们需要额外添加状态的时候,添加一个新的状态,或者在原有的状态下,添加一个新的属性会发生什么,这个新的状态并不在组件劫持的状态之内:
当我们点击按钮的时候,视图中的 ui 并没有发生更改,根据官方的文档,我们可以使用 $set 针对新增的状态进行修改
除了后续新增的状态无法进行修改之外,使用 Object.defineProperty 劫持的数据,对数组本身可以操作的到,但是会存在一定的性能问题,具体不做详细解释,可以参考以下博文,感谢该博主的博文,vue 的框架的作者尤大也做了解释:
记一次思否问答的问题思考:Vue为什么不能检测数组变动 https://segmentfault.com/a/1190000015783546
结语
根据以上例子结合 vue 响应式原理,我们可以知道在 vue2.x 版本中 Object.defineProperty 存在以下问题:
1.监听数组变化下存在性能问题 2.Object.defineProperty 只能劫持对象的属性,并且针对新增的 data 状态,无法劫持到,只能通过 vue 的扩展方法 $set 进行处理
扩展 vue3 使用的 proxy
阮一峰-ECMAScript 6 入门查看最简单的例子和使用方法
下文截取自:阮一峰-ECMAScript 6 入门----> Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”
Object.defineProperty 对比 Proxy 个人理解
Proxy 是针对整个对象的变化进行检测和拦截,可以知道对象的属性是新增,删除,还是修改等,都可以通过通过 get 和 set 进行监听得到
Object.defineProperty 只针对对象得属性进行操作,结合 vue2.x,组件渲染完成,后续新增得属性,没办法劫持到
Object.defineProperty 针对属性,Proxy 针对整个对象得操作
更多 Object.defineProperty 和 Proxy 的对比,以及 vue3 如果使用 proxy 实现对象的监听,感兴趣的同学可以去搜索相关博文,后续有时间再整理。
源码地址
文章个人博客地址:vue2.x版本中Object.defineProperty对象属性监听和关联
欢迎关注公众号:程序猿布欧,不定期更新一些前端入门文章
创作不易,转载请注明出处和作者。
版权声明: 本文为 InfoQ 作者【程序猿布欧】的原创文章。
原文链接:【http://xie.infoq.cn/article/bc2b8fd4bf6aa153ab7e81f31】。文章转载请联系作者。
评论