Vue源码解读

469 阅读1分钟

一、版本说明

  • 1、npm i vue -S 得到最新版本的 vue(v2.6.8)
  • 2、如下图,找到dist里面的vue.js即可

目录结构

二、原型与原型链

1、实例的属性和方法(下图)

实例的属性和方法

2、原型上的属性和方法(下图)

原型上的属性和方法

3、原型链(下图)

原型链
上图有误,后续修正

const vm = new Vue()之后有:

vm.__proto__ === Vue.prototype
vm.__proto__.__proto__ === Object.prototype
vm.__proto__.__proto__.__proto__===null

Vue.__proto__ === Function.prototype
Vue.__proto__.__proto__ === Object.prototype
Vue.__proto__.__proto__.__proto__===null

三、Vue是如何执行的?

3-1、Vue的初始化过程

查看vue的源码,实例化之后会执行原型链上的__init方法,该方法执行了一系列初始化动作:

function Vue(options) {
    if (!(this instanceof Vue)) {
        warn('Vue is a constructor and should be called with the `new` keyword');
    }
    this._init(options);
}

Vue.prototype._init = function (options) {
    initLifecycle(vm); // 把一些全局的属性绑定到vm里面
    initEvents(vm); // 把一些全局的事件绑定到vm里面
    initRender(vm); // 渲染初始化,createElement()绑定等
    callHook(vm, 'beforeCreate');
    initInjections(vm); // resolve injections before data/props
    initState(vm); // 把vm的属性和方法初始化,包括props、data、methods、钩子函数等所有属性,并完成对data的数据劫持及加入观察者
    initProvide(vm); // resolve provide after data/props
    callHook(vm, 'created');
    
    //判断是否有el,有则执行$mount(),没有的话什么都不做
    if (vm.$options.el) { 
        vm.$mount(vm.$options.el);
    }
}

可以看到初始化动作做了很多事情,这也是为什么说vue初始化的时候比react慢。

3-2、初始化之后又做了什么?

3-2-1、看源码,初始后之后开始 mountComponent()

Vue.prototype.$mount = function (el, hydrating) {
    el = el && inBrowser ? query(el) : undefined;
    return mountComponent(this, el, hydrating)
};

3-2-2、mountComponent() 主要做了4件事

  • 1、执行 beforeMount 钩子
  • 2、执行原型链上的 _render()、_update() 2个函数
  • 3、设置Watch,若有更新,则执行 beforeUpdate 钩子
  • 4、执行 mounted 钩子

callHook(vm, 'beforeMount');

vm._update(vm._render())

new Watcher(vm, updateComponent, noop, {
    before: function before() {
        if (vm._isMounted && !vm._isDestroyed) {
            callHook(vm, 'beforeUpdate');
        }
    }
}, true /* isRenderWatcher */);

if (vm.$vnode == null) {
    vm._isMounted = true;
    callHook(vm, 'mounted');
}

3-2-3、_render()一点说明(做了啥?)

vm._render() --> vm.$createElement() --> createElement()
--> createComponent() --> installComponents()
--> componentVNodeHooks{
    init(){},
    prepatch(){},
    insert(){-->callHook(vm, 'mounted')},
    destroy(){}
}

四、(待续)