Vue源码分析 (一) ---- 响应式系统基本原理

最近准备好好看看《Vue的内部运行机制》,学到什么就写什么,先介绍Vue的响应式主要核心API

Object.defineProperty(obj, key, descriptor)

descriptor其中有几个属性:

configurable  --》属性可配置性,属性是否可修改或删除,默认false

enumerable --》属性可枚举性,默认false

value --》属性值,默认undefined

writable --》属性可写性,默认false

get --》 get函数set --》set函数

注意:显示声明对象与调用definePropperty函数设置的属性配置不一样

以上两个例子,可以认真看一下

简单实现Observer

首先我们先设定一个更改页面视图的函数

function cb(value) {
    document.querySelector('.Test').innerHTML = value;
}

 然后我们定义一个 defineReactive ,这个方法通过 Object.defineProperty 来实现对对象的「响应式」化

/**
 * 将属性响应式化函数
 * 
 * @param {object} obj 响应式化对象
 * @param {} key 响应式对象属性
 * @returns {} val 旧属性值
 * 
 */
function defineReactive(obj, key, val) {
    Object.defineProperty(obj, key, {
        enumerable: true,
        /* 可枚举 */
        configurable: true,
        /* 可配置修改或删除 */
        get: function reactiveGetter() { /* 应该依赖采集 */
            return val;
        },
        set: function reactiveSetter(newVal) {
            if (newVal === val) {
                return;
            }
            val = newVal;
            cb(val);
        }
    })
}

我们需要在上面再封装一层 observe 函数 。这个函数传入一个 value(需要「响应式」化的对象),通过遍历所有属性的方式对该对象的每一个属性都通过 defineReactive 处理。

/**
 * 将对象所有属性响应式化函数
 * 
 * @param {object} value 响应式化对象
 * 
 */
function observer(value) {
    if (!value || (typeof value !== 'object')) {
        return;
    }
    /* 遍历value中属性定制set和get */
    Object.keys(value).forEach(key => defineReactive(value, key, value[key]));
}

然后尝试封装一个简单的 Vue 类

/**
 * Vue构造类
 */
class Vue {
    constructor(options) {
        this._data = options.data;
        observer(this._data);
    }
}

这样我们只要 new 一个 Vue 对象,就会将 data 中的数据进行「响应式」化。如果我们对 data 的属性进行下面的操作,就会触发 cb 方法更新视图。

var test = new Vue({
    data: {
        test: 'I am test Vue.'
    }
});

页面结构

<body>
    <div class="Test">I am test Vue.</div>
</body>

测试结果

在控制台我们尝试修改test对象中的 _data 属性,页面视图也已经被更新

参考文章

《Vue的内部运行机制》

本节代码参考《响应式系统的基本原理》

猜你喜欢

转载自blog.csdn.net/LL18781132750/article/details/81389881
今日推荐