数据对象实现响应式

本文深入探讨了Vue.js中响应式数据的实现机制,解析了如何通过Object.defineProperty()来实现数据对象的监听与更新,以及这种机制在JavaScript中的工作方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

响应式数据的实现原理

      const data = {
        name: 'zs',
        age: 18,
        gender: '女',
        hobby: {
          name1: 'ball1',
          name2: 'ball2',
          name3: 'ball3'
        },
        num: [{ z: 1 }, { s: 2 }, { j: 3 }]
      }
		
	  // # 辅助函数 对数组方法进行加工		
      const ARRAY_METHOD = ['push', 'pop', 'shift', 'unshift', 'reverse', 'splice', 'sort']
      // 原型继承 array_method.__proto__ 指向 Array.prototype
      const array_method = Object.create(Array.prototype)
      // TODO:数组部分方法改造成响应式  方法重写(拦截)
      ARRAY_METHOD.forEach((key) => {
        array_method[key] = function () {
          // 方法重写(拦截)
          // 将新添加的数据进行响应式化
          for (let i = 0; i < arguments.length; i++) {
            deepSetReactive(arguments[i])
          }

          // 执行数组原型上的方法
          return Array.prototype[key].apply(this, arguments)
        }
      })

      // 定义得到响应式数据的方法
      function defineReactiveProperty(target, key, value, enumerable) {
        // TODO:对非数组的引用类型进行拦截,进行响应式注册
        if (typeof value === 'object' && value != null && !Array.isArray(value)) {
          deepSetReactive(value)
        }
        Object.defineProperty(target, key, {
          configurable: true, // 可配置的
          enumerable: !!enumerable, // 是否可枚举
          get() {
            console.log('调用:' + key)
            return value
          },
          set(newVal) {
            console.log('设置:' + key + '-->' + newVal)
            // ! 新添加的值响应式化
            if (typeof newVal === 'object' && newVal != null) {
              deepSetReactive(newVal)
            }
            value = newVal
          }
        })
      }

      // 递归实现所有数据的响应式注册
      function deepSetReactive(data) {
        Object.keys(data).forEach((key) => {
          let value = data[key]
          if (Array.isArray(value)) {
            // 数组自身地址的响应式
            defineReactiveProperty(data, key, value, true)
            // 数组方法重写
            value.__proto__ = array_method
            // 如果是数组则遍历注册,这里是对数组内部进行响应式注册
            value.forEach((item) => {
              deepSetReactive(item)
            })
          } else {
            // 除数组外的数据类型均在这里进行响应式注册
            defineReactiveProperty(data, key, value, true)
          }
        })
      }

      deepSetReactive(data)
      console.log(data)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值