深入浅出 Vue 系列 -- 数据劫持实现原理

本文深入探讨 Vue 的数据劫持技术,包括对 Object 类型的劫持,如属性描述符、getter 和 setter,以及处理数组的特殊性和常用方法的劫持。Vue 使用 Object.defineProperty() 遇到的挑战,如每次只能设置一个属性和 configurable 的限制,以及如何避免递归爆栈问题。同时,文章指出 Vue3.0 中 Proxy 的优势。
摘要由CSDN通过智能技术生成

一、前言

  数据双向绑定作为 Vue 核心功能之一,其实现原理主要分为两部分:

  • 数据劫持
  • 发布订阅模式

  本篇文章主要介绍 Vue 实现数据劫持的思路,下一篇则会介绍发布订阅模式的设计。

二、针对 Object 类型的劫持

  对于 Object 类型,主要劫持其属性的读取与设置操作。在 JavaScript 中对象的属性主要由一个字符串类型的“名称”以及一个“属性描述符”组成,属性描述符包括以下选项:

  • value: 该属性的值;
  • writable: 仅当值为 true 时表示该属性可以被改变;
  • get: getter (读取器);
  • set: setter (设置器);
  • configurable: 仅当值为 true 时,该属性可以被删除以及属性描述符可以被改变;
  • enumerable: 仅当值为 true 时,该属性可以被枚举。

  上述 setter 和 getter 方法就是供开发者自定义属性的读取与设置操作,而设置对象属性的描述符则少不了 Object.defineProperty() 方法:

function defineReactive (obj, key) {
  let val = obj[key]
  Object.defineProperty(obj, key, {
    get () {
      console.log(' === 收集依赖 === ')
      console.log(' 当前值为:' + val)
      return val
    },
    set (newValue) {
      console.log(' === 通知变更 === ')
      console.log(' 当前值为:' + newValue)
      val = newValue
    }
  })
}

const student = {
  name: 'xiaoming'
}

defineReactive(student, 'name') // 劫持 name 属性的读取和设置操作

  上述代码通过 Object.defineProperty() 方法设置属性的 setter 与 getter 方法,从而达到劫持 student 对象中的 name 属性的读取和设置操作的目的。

  读者可以发现,该方法每次只能设置一个属性,那么就需要遍历对象来完成其属性的配置:

  Object.keys(student).forEach(key => defineReactive(student, key))

  另外还必须是一个具体的属性,这也非常的致命。

  假如后续需要扩展该对象,那么就必须手动为新属性设置 setter 和 getter

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值