vue2.0观察对象实现原理

201 阅读1分钟

  • vue2.0 通过Object.defineProperty
  • vue3.0 通过Proxy

实现原理

const arrProto = Array.prototype;
const newArrProto = Object.create(arrProto);
['push', 'unshift', 'splice', 'reverse', 'sort', 'shift', 'pop'].forEach(method => {
    newArrProto[method] = function(...args) {
        let inserted;
        switch (method) {
            case 'push':
            case 'unshift':
                {
                    inserted = args;
                    break;
                }
            case 'splice':
                {
                    inserted = args.slice(2);
                }
            default:
                break;
        }
        observerArray(inserted);
        arrProto[method].call(this, ...args);
    };
});

function observer(obj) {
    if (typeof obj !== 'object' || obj == null)
        return obj;
    if (Array.isArray(obj)) {
        Object.setPrototypeOf(obj, newArrProto);
        observerArray(obj);
    } else {
        // 都是对象方式
        for (let i in obj) {
            let item = obj[i];
            defineProperty(obj, i, item);
        }
    }
}

function defineProperty(obj, key, value) {
    observer(value); //值也是对象
    Object.defineProperty(obj, key, {
        get() {
            return value;
        },
        set(newVal) {
            if (newVal != value) {
                observer(newVal);
                value = newVal;
                update();
            }
        },
    })
}

function observerArray(obj) {
    for (let item of obj) {
        // 普通值不会监控
        observer(item);
    }
}

function update() {
    console.log('视图更新');
}

简单对象

// 简单对象
// let obj = {
//     name: 'jaasdsa',
// }
// observer(obj);
// obj.name = 'jj';

对象值也是对象

// let obj = {
//     name: {
//         n1: 'jaasdsa'
//     },
// }
// observer(obj);
// obj.name.n1 = 'jj';

对象设置值的时候也有可能是对象

// let obj = {
//     name: 'jaasdsa'
// }
// observer(obj);
// obj.name = { n1: 'jj' };
// obj.name.n1 = 'kk';

对象是数组

// 对象是数组
// let obj = [1, 2, 3];
// observer(obj);
// obj[0] = 11;

数组成员是对象会被监控

// 数组成员是对象会被监控
// let obj = [{ name: 'jj' }];
// observer(obj);
// obj[0].name = 11;

数组通过push,unshift,splice添加的对象也能监控到

//数组通过push,unshift,splice添加的对象也能监控到
let obj = [];
observer(obj);
obj.push({ name: 'jj' });
obj[0].name = 11;