手撕Vue

167 阅读1分钟

vue源码笔记

先吃透下面这个家伙,vue的响应式就这玩意。不用多说,直接上家伙。

Object.defineProperty

/*
    obj: 目标对象
    prop: 需要操作的目标对象的属性名
    descriptor: 描述符
    return value 传入对象
*/
Object.defineProperty(obj, prop, descriptor)

属性: descriptor的一些属性,简单介绍几个属性,具体可以参考 MDN 文档。

  • enumerable,属性是否可枚举,默认 false。
  • configurable,属性是否可以被修改或者删除,默认 false。
  • get,获取属性的方法。
  • set,设置属性的方法。

vue响应式系统的基本原理——写出自己的vue:

<!--这个函数传入一个 value(需要「响应式」化的对象),通过遍历所有属性的方式对该对象的每一个属性都通过 defineReactive 处理。(注:实际上 observer 会进行递归调用,为了便于理解去掉了递归的过程)-->
function observer (value) {
    if (!value || (typeof value !== 'object')) {
        return;
    }
    
    Object.keys(value).forEach((key) => {
        defineReactive(value, key, value[key]);
    });
}

<!--首先我们定义一个 cb 函数,这个函数用来模拟视图更新,调用它即代表更新视图,内部可以是一些更新视图的方法。-->
function cb (val) {
 /* 渲染视图 */
    console.log("视图更新啦~", val);
}


<!--然后我们定义一个 defineReactive ,这个方法通过 Object.defineProperty 来实现对对象的「响应式」化,入参是一个 obj(需要绑定的对象)、key(obj的某一个属性),val(具体的值)。经过 defineReactive 处理以后,我们的 obj 的 key 属性在「读」的时候会触发 reactiveGetter 方法,而在该属性被「写」的时候则会触发 reactiveSetter 方法。-->
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(newVal);
        }
    });
}

<!--在 Vue 的构造函数中,对 options 的 data 进行处理,这里的 data 想必大家很熟悉,就是平时我们在写 Vue 项目时组件中的 data 属性(实际上是一个函数,这里当作一个对象来简单处理)。-->

class Vue {
    constructor(options) {
        this._data = options.data;
        observer(this._data);
    }
}

<!--这样我们只要 new 一个 Vue 对象,就会将 data 中的数据进行「响应式」化。如果我们对 data 的属性进行下面的操作,就会触发 cb 方法更新视图。-->
let o = new Vue({
    data: {
        test: "I am test."
    }
});
o._data.test = "hello,test.";

到此,你自己的vue雏形就出来了,吃透这些,行走IT江湖不在怕!奥里给!