VUE初始化的主要过程

new Vue后发生了什么?

以下为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)
}

 可见在new Vue后,构造函数内部调用了_init方法,其中_init方法源码如下:

Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    // a uid
    vm._uid = uid++

    let startTag, endTag
    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      startTag = `vue-perf-start:${vm._uid}`
      endTag = `vue-perf-end:${vm._uid}`
      mark(startTag)
    }

    // a flag to avoid this being observed
    vm._isVue = true
    // merge options
    if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else {
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }
    /* istanbul ignore else */
    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')
    initInjections(vm) // resolve injections before data/props
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')

    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      vm._name = formatComponentName(vm, false)
      mark(endTag)
      measure(`vue ${vm._name} init`, startTag, endTag)
    }

    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  }

大概讲讲,部分忽略 

1.添加uid

vm._uid = uid++

给当前实例添加一个唯一的uid标识。

2.合并options

    // merge options
    if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else {
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }

首先通过_isComponent判断该组件是否为子组件

为子组件:调用initInternalComponent函数,其主要做了两件事情:1.指定组件$options原型,2.把组件依赖于父组件的props、listeners也挂载到options上,方便子组件调用。

为根组件:对 options 进行合并,vue 会将相关的属性和方法都统一放到 vm.$options 中。vm.$options 的属性来自两个方面,一个是 Vue 的构造函数 vm.constructor 预先定义的,一个是 new Vue 时传入的入参对象。

3.initProxy

在非生产环境下执行了 initProxy 函数,参数是实例;在生产环境下设置了实例的 _renderProxy 属性为实例自身。

将实例的 _self 属性设置为实例自身。

4.initLifecycle

初始化组件实例关系属性 , 比如 $parent$children$root$refs 等 (不是组件生命周期 mounted , created…)。

5.initEvents

function initEvents (vm: Component) {
  // 存放事件的空对象
  vm._events = Object.create(null)
  vm._hasHookEvent = false
  // init parent attached events(初始化父组件绑定在该组件上的事件)
  const listeners = vm.$options._parentListeners
  if (listeners) {
    updateComponentListeners(vm, listeners)
  }
}

这个函数的功能就是初始化了一个存放事件的空对象,只存放挂载在该组件上的事件。_hasHookEvent属性是表示父组件是否有将钩子函数绑定到该组件上。如果父组件有绑定事件到该组件上则调用updateComponentListeners方法,下面看一下该方法的实现

function updateComponentListeners (
  vm: Component,
  listeners: Object,
  oldListeners: ?Object
) {
  target = vm
  updateListeners(listeners, oldListeners || {}, add, remove, vm)
  target = undefined
}

其中addremove是Vue中自己实现的两个添加Listener、移除Listener的方法。 

6.initRender

初始化插槽 , 获取 this.slots , 定义 this._cthis.$createElement方法。其中_c 用于从模板<template>编译得到的组件中使用,通常是vue内部使用生成vnode,而$createElement是放给用户用作render渲染写法。

// a: 标签
// b: 标签属性
// c: children
// d: normalizationType(是否需要额外兜底处理)
vm._c = (a, b, c,d) => createElement(vm, a, b, c, d, false);
vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true);

7.callHook(vm, 'beforeCreate')

执行 beforeCreate 生命周期函数。

8.initInjections

初始化 inject 选项。

9.initState

响应式原理的核心 , 处理 propsmethodscomputeddatawatch 等。

10.initProvide

解析组件配置项上的 provide 对象,将其挂载到 vm._provided 属性上。

11.callHook(vm, 'created')

执行 create 生命周期函数。

最后判断vm.$options.el属性是否存在

存在:调用 vm.$mount 方法挂载 vm ,挂载的目标就是把模板渲染成最终的 DOM

不存在new Vue时手动挂载。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值