vue源码深入浅出系列-vue实例挂载的实现1

776 阅读2分钟

数据驱动

相信大家都知道,Vue.js 一个核心思想是数据驱动。所谓数据驱动,是指视图是由数据驱动生成的,我们对视图的修改,不会直接操作 DOM,而是通过修改数据。它相比我们传统的前端开发,如使用 jQuery 等前端库直接修改 DOM,大大简化了代码量。 在 Vue.js 中我们可以采用简洁的模板语法来声明式的将数据渲染为 DOM:

<div id="app">

  {{ message }}

</div>

var app = new Vue({

  el: '#app',

  data: {

    message: 'Hello Vue!'

  }

})

最终它会在页面上渲染出 Hello Vue,了解真正的原理那我们从源码入口开始看吧

new Vue 的执行过程发生了什么

小源码分析

从入口代码开始分析,我们先来分析 new Vue 背后发生了哪些事情。我们都知道,new 关键字在 Javascript 语言中代表实例化是一个对象,而 Vue 实际上是一个类,类在 Javascript 中是用 Function 来实现的,来看一下源码,在src/core/instance/index.js 中。

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)
}

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

其实这里就可以看到它的庐山真面目,这里vue实例的时候就是执行原型上的inti方法,问题来了,原型的上面是什么时候挂载上去的呢,其实下面的initMixin,**Mixin等,就是定义vue的原型方法,其实我们项目中经常见的ononemit$off就是在这个时候挂载在vue原型上面的,

image.png 我们这次的主角是_init,我们来继续看看初始化方法到底做了什么

image.png

Vue 初始化主要就干了几件事情,合并配置,初始化生命周期,初始化事件中心,初始化渲染,初始化 data、props、computed、watcher 等等。

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

init方法最终的目标就是走mount方法,可以说,前面的都是做铺垫,其实mount方法,可以说,前面的都是做铺垫,其实mount方法在文件entry-runtime-with-compiler.js以及定义了,下一讲我们会着重分析这个$mount方法,看看它是怎么实现的,解开他的神秘面纱。

小总结

Vue 的初始化逻辑写的非常清楚,把不同的功能逻辑拆成一些单独的函数执行,让主线逻辑一目了然,这样的编程思想是非常值得借鉴和学习的。

由于我们这一章的目标是弄清楚模板和数据如何渲染成最终的 DOM,所以各种初始化逻辑我们先不看。在初始化的最后,检测到如果有 el 属性,则调用 vm.$mount 方法挂载 vm,挂载的目标就是把模板渲染成最终的 DOM,那么接下来我们来分析 Vue 的挂载过程。