vue2数据响应式

这是一个简单的 JavaScript 数据响应式 实现示例,使用了 Object.defineProperty 来拦截属性的读取和设置操作。下面是对代码的逐行解析:


代码分析

javascript 复制代码
function observe(obj) {
    for (const key in obj) {
        let internalValue = obj[key];
        Object.defineProperty(obj, key, {
            get: function () {
                // 记录:是哪个函数在用我
                return internalValue;
            },
            set: function (val) {
                internalValue = val;
                // 运行:执行用我的函数
            },
        });
    }
}

1. 函数目的

  • 将传入的对象 obj 转换为响应式对象:当属性被读取或修改时,可以执行额外操作(如依赖收集、触发更新)。

2. 遍历对象属性

javascript 复制代码
for (const key in obj) {
  • 遍历 obj 的所有可枚举属性。

3. 闭包保存属性值

javascript 复制代码
let internalValue = obj[key];
  • 用局部变量 internalValue 保存属性当前值,避免在 getter/setter 中直接使用 obj[key] 导致递归调用。

4. 使用 Object.defineProperty 重定义属性

javascript 复制代码
Object.defineProperty(obj, key, { ... });
  • 将每个属性转为 getter/setter,实现拦截。

5. Getter

javascript 复制代码
get: function () {
    // 记录:是哪个函数在用我
    return internalValue;
}
  • 当属性被读取时,返回 internalValue
  • 注释提示这里可以用于依赖收集(例如 Vue 2 中记录当前正在执行的渲染函数或计算属性)。

6. Setter

javascript 复制代码
set: function (val) {
    internalValue = val;
    // 运行:执行用我的函数
}
  • 当属性被修改时,更新 internalValue
  • 注释提示这里可以用于触发更新(例如通知所有依赖该属性的函数重新执行)。

存在的问题

  1. 只能拦截已有属性 :如果后续给对象新增属性,不会被响应式处理(Vue 2 中需用 Vue.set)。
  2. 数组变异方法不支持 :如 pushpop 等不会触发 setter(Vue 2 中通过重写数组方法解决)。
  3. 性能问题:遍历所有属性并重定义,对于大对象或频繁操作可能影响性能。
  4. 嵌套对象未处理 :如果属性值是对象,需要递归调用 observe 才能实现深层响应式。

改进示例(支持深层响应式)

javascript 复制代码
function observe(obj) {
    if (typeof obj !== 'object' || obj === null) return;

    for (const key in obj) {
        let internalValue = obj[key];
        observe(internalValue); // 递归处理嵌套对象
        Object.defineProperty(obj, key, {
            get: function () {
                console.log(`读取 ${key}: ${internalValue}`);
                return internalValue;
            },
            set: function (val) {
                console.log(`设置 ${key} 为 ${val}`);
                internalValue = val;
                observe(val); // 新值是对象时也转为响应式
            },
        });
    }
}
相关推荐
咩咩啃树皮7 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
阳光是sunny7 小时前
LangGraph中的Reducer是什么
前端·人工智能·后端
触底反弹7 小时前
一文搞懂 Tailwind CSS 弹性布局:从原理到实战
前端·css·html
阳光是sunny7 小时前
从链到图:LangGraph 入门基础全解析
前端·人工智能·后端
小林ixn7 小时前
从 ??= 到 onKeyDown:一个 React 组件的“自我修养”
前端·javascript·react.js
REDcker8 小时前
显示分辨率标准对照详解
前端·网络·分辨率·显示·屏幕
এ慕ོ冬℘゜8 小时前
前端实战:jQuery 多条件联合搜索(标题模糊查询 + 日历时间段筛选)
前端·javascript·jquery
武子康8 小时前
Search Console Platform Properties 扩大 SEO 资产边界:从 Page Ranking 到 Topic Coverage(5 类误读边界 + 3 表数据层设计)
前端·人工智能·后端
一点一木9 小时前
从60首歌到1个网站:输入你的故事,还你一首歌
前端·github
IT_陈寒10 小时前
Vue这个特性差点让我加班到凌晨,谁懂啊
前端·人工智能·后端