Vue实例初始化之 _init 方法

版权声明:转载请注明出处! https://blog.csdn.net/zjq_1314520/article/details/87996164

打开 Vue 源码, 在其入口文件 core/instance/index 代码中,我们可以看到 Vue 类定义如下

function Vue(options) { 
  if (process.env.NODE_ENV !== 'production'
    && !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword');
  }
  this._init(options);  // 调用 _init 进行一些初始化工作
}

可知这段代码实际上只做了一件事,在 Vue 实例创建的时候调用了 其本身的 _init 方法。

那么这个方法是这哪里定义的呢? 我们往下看,会看到一个初始化 mixin 的代码

initMixin(Vue);

我们在 initMixin 函数中找到了这个_init方法的定义,代码如下
为了让代码看起来简洁一些,这里我们将有关 performance 配置处理的代码去掉

let uid = 0;

export function initMixin(Vue: Class<Component>) {
  Vue.prototype._init = function(options?: Object) {
    const vm: Component = this;

    vm._uid = uid++; // 当前实例的 _uid 加 1

	//  a flag to avoid this being observed
    // 用 _isVue 来标识当前实例是 Vue 实例, 这样做是为了后续被 observed
    vm._isVue = true;
    
    // merge options 合并options 
    if (options && options._isComponent) { // _isComponent 标识当前为 内部Component
      // 内部Component 的 options 初始化
      initInternalComponent(vm, options); 
    }
    else { // 非内部Component的 options 初始化
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      );
    }
    
    // 在render中将this指向vm._renderProxy
    if (process.env.NODE_ENV !== 'production') {
      initProxy(vm);
    }
    else {
      vm._renderProxy = vm;
    }
    // expose real self
    vm._self = vm;
    initLifecycle(vm); // 初始化生命周期
    initEvents(vm); // 初始化事件
    initRender(vm); // 初始化渲染函数
    callHook(vm, 'beforeCreate'); // 回调 beforeCreate 钩子函数
    initInjections(vm); // resolve injections before data/props
    // 初始化 vm 的状态
    initState(vm);
    initProvide(vm); // resolve provide after data/props
    callHook(vm, 'created'); // vm 已经创建好 回调 created 钩子函数

    if (vm.$options.el) { // 挂载实例
      vm.$mount(vm.$options.el);
    }
  };
}

一遍代码读下来,可知在初始化方法中主要干了以下几件事

  1. 初始化 options 参数
  2. 将 _renderProxy 设置为 vm
  3. 初始化生命周期
  4. 初始化 Render
  5. 初始化 vm的状态,prop/data/computed/method/watch都在这里完成初始化
  6. 挂载实例

对于上面的代码我们还有如下的疑惑

  1. 为什么要特别处理内部Component,以及 initInternalComponent 函数的实现
  2. mergeOptions 函数是如何实现的
  3. 为什么在开发环境是调用initProxy,而在正式环境则直接将_renderProxy复制为vm本身
  4. 初始化 生命周期,Render,vm的状态 等是如何实现的
  5. 怎样挂载实例的

对此我们将在下次文章中介绍。

欢迎关注微信公众号,会有最新的文章: 子曰思鱼
在这里插入图片描述

展开阅读全文

没有更多推荐了,返回首页