vue 数据响应式原理 - 递归侦测对象的全部属性

  • 官网的响应式原理图解:

  • 三种框架的数据变化类型:

  • Object.defineProperty() 方法:

  • Object.defineReactive() 方法:
let obj = {};
function defineReactive(data, key, val) {
    Object.defineProperty(data, key, {
        // 可枚举
        emuerable: true,
        // 可以被配置,比如可以被 delete
        configurable: true,
        get() {
            console.log(`正在访问obj的${key}属性`, val);
            return val;
        },
        set(newValue) {
            console.log(`正在改变obj的${key}属性`, newValue);
            if (val === newValue) { return };
            val = newValue;
        }
    })
}
defineReactive(obj, 'a', 10);
defineReactive(obj, 'b', 30);
obj.a = 30;
obj.a++;
obj.b = 66;
console.log(obj.a);
console.log(obj.b);
  • 递归侦测对象全部属性

 

 

 

 文件目录:

 

 index.js

import observe from './observe';
let obj = {
    a: {
        m: {
            n: {
                e: {
                    f: 5
                }
            }
        }
    },
    b: 3
};
observe(obj);
obj.a.m.n.e.f = 10;

observe.js

import Observer from './Observer.js';
// 创建 observe 函数,注意函数的名字没有r
export default function observe (value) {
    // 函数只为对象服务
    if (typeof value !== 'object') return;
    // 定义 ob
    let ob;
    if (typeof value.__ob__ !== 'undefined') {
        ob = value.__ob__;
    } else {
        ob = new Observer(value);
    }
    return ob;
}

Observer.js

import { def } from './utils.js';
import defineReactive from './defineReactive.js';
export default class Observer {
    constructor(value) {
        console.log('我是Observer的构造器', value);
        // 给实例(构造函数中的this表示实例)添加了__ob__属性
        def(value, '__ob__', this, false);
        console.log('我是Observer构造器', value);
        // Observer类的目的是:将一个正常的 object 转换为每个层级的属性都是响应式(可以被侦测的)的 object
        this.walk(value);
    }
    // 遍历
    walk(value) {
        for (let key in value) {
            defineReactive(value, key);
        }
    }
}

defineReactive.js

import observe from './observe';
export default function defineReactive(data, key, val) {
    console.log('我是defineReactive', data, key);
    if (arguments.length == 2) {
        val = data[key];
    }
    // 子元素要进行 observe, 至此形成了递归,
    // 这个递归不是函数自己调用自己
    let childOb = observe(val);
    Object.defineProperty(data, key, {
        // 可枚举
        emuerable: true,
        // 可以被配置,比如可以被 delete
        configurable: true,
        get() {
            console.log(`正在访问${key}属性`, val);
            return val;
        },
        set(newValue) {
            console.log(`正在改变${key}属性`, newValue);
            if (val === newValue) { return };
            val = newValue;
            // 当设置了新值,新值也要 observe
            childOb = observe(newValue);
        }
    })
}

utils.js

export const def = function(obj, key, value, emurable) {
    Object.defineProperty(obj, key, {
        value,
        emurable,
        writable: true,
        configurable: true
    })
}

 

posted @ 2021-08-29 22:57  我就尝一口  阅读(188)  评论(0编辑  收藏  举报