Vue 的源码结构比较绕,同时使用了大量的面向对象的高级技巧。重写方法,扩展方法,多态等应用。从 Vue 实例的加载过程就可以看出来,这一节重点看看 Vue 的源码加载流程是什么。
前言
vue已是目前国内前端web端三分天下之一,同时也作为本人主要技术栈之一,在日常使用中知其然也好奇着所以然,另外最近的社区涌现了一大票vue源码阅读类的文章。在下借这个机会从大家的文章和讨论中汲取了一些营养,同时对一些阅读源码时的想法进行总结,出产一些文章,作为自己思考的总结。
前备知识
- Flow
- ES6语法
- 常用的设计模式
- 柯里化等函数式编程思想
一、vue简介和初始化过程
vue的源码结构如下:
A.compiler 编译用的
a.vue 使用字符串作为模板
b.在编译文件夹中存放对 模板字符串的 解析的算法, 抽象语法树, 优化等
B.core 核心, vue 构造函数, 以及生命周期等方法的部分
C.platforms 平台
a.针对运行的环境 ( 设备 ), 有不同的实现
b.也是 vue 的入口
D.server 服务端, 主要是将 vue 用在服务端的处理代码 ( 略 )
E.sfc, 单文件组件 ( 略 )
F.在编译文件夹中存放对 模板字符串的 解析的算法, 抽象语法树, 优化等shared 公共工具, 方法
二、Vue对象
在使用vue时我们知道都是使用new Vue(),来将vue的实例挂载到dom对象上从而运用数据驱动的方式来扩展我们的代码,我们首先来看一下Vue的定义
从源头上看来自core目录下的index.js文件
在js中一切皆函数,其实Vue就是一个函数,在初始化的时候执行原型链上的_init方法,vue没有把所有的方法都写在函数内部,这样从代码上来说,每次实例化的时候不会生成重复的代码。
主要还是代码结构更清晰,利用mixin的概念,把每个模块都抽离开,这样代码在结构和扩展性都有很大提高,这里的每个mixin先不说,先看以一下整体结构,这里定义完还要被core里的index.js再次包装调用initGlobalAPI(Vue)来初始化全局的api方法。
在web下runtime文件夹下引用再次封装,vue是分为运行时可编译和只运行的版本,所以如果需要编译,在Vue原型上添加了$mount方法。
三、运行机制
当我们在 main.js 里 new Vue( ) 后,Vue 会调用构造函数的 _init( ) 方法,这个方法是位于 core/instance/index.js 的 initMixin( ) 方法中定义的
我们可以看看 init( ) 这个方法到底进行了哪些初始化:
这里 _init() 方法中会对当前 vm 实例进行一系列初始化设置,比较重要的是初始化 State 的方法 initState(vm) 的时候进行 data/props 的响应式化,这就是传说中的通过 Object.defineProperty() 方法对需要响应式化的对象设置 getter/setter,以此为基础进行依赖搜集(Dependency Collection),达到数据变化驱动视图变化的目的。
最后检测 vm.$options 上面有没有 el 属性,如果有的话使用 vm.$mount 方法挂载 vm,形成数据层和视图层的联系。这也是如果没有提供 el 选项就需要自己手动 vm.$mount('#app') 的原因。
我们看到 created 钩子是在挂载 $mount 之前调用的,所以我们在 created 钩子触发之前是无法操作 DOM 的,这是因为还没有渲染到 DOM 上。
四、总结
一张图看一下整个流程
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。