Vue学习笔记 — 整体流程

Vue的整体流程对一些业务实现很有帮助,当出现一些bug时我们可以根据所使用功能的内部实现,快速、精确地定位问题所在,当我们理解了Vue.js能提供的能力边界在哪里的时候,我们就可以最大限度地发挥它的价值

目录结构

  • script # 与构建相关的脚本和配置文件

  • dist # 构建后的文件

  • flow # Flow的类型声明

  • package # vue-server-randerervue-template-compiler,他们可以作为单独的npm包发布

  • test # 所有的测试代码

  • src # 源代码

    • compiler # 模板编译相关的代码(解析器、、优化器、代码生成器)
    • core # 通用的、与平台无关的运行时代码
      • observer # 变化侦测相关代码
      • vdom # 虚拟dom相关代码
      • instance # Vue.js 实例的构造函数与原型方法
      • global-api # 全局的API代码
      • components # 通用的抽象组件
    • server # 服务端渲染相关代码
    • platforms # 特定平台相关代码
    • sfc # 单文件组件(*.vue文件)解析逻辑
    • shared # 整个项目的公用工具代码
  • types # TypeScript类型定义

    • test # 类型定义测试

当使用vue-loader或vueify的时候,*.vue文件内部的模板会在构建时预编译成JavaScript。

开发环境与生产环境模式

对于UMD版本来说,开发发环境和生产环境二者的模式是硬编码的:开发环境下使用未压缩的代码,生产环境下使用压缩后的代码。

CommonJsES Module 版本应用于打包工具,因此Vu.js不提供压缩后的版本,需要自行将最终的包进行压缩。他们还保留原始的process.env.NODE_ENV检测,这会决定他们应该在什么模式下运行。我们应该使用适当的打包工具来替换这些环境变量,以便控制Vue.js所运行的模式。把process.env.NODE_ENV替换为字符串字面量,同时使用UglifyJS之类的压缩工具完全删除仅供开发环境的代码块,从而减小最终文件的大小。

在Vue.js中,我们使用DefinePlugin

1
2
3
4
5
6
7
8
9
10
11
12
var webpack = require('webpack')

module.export = {
//...
plugins: [
new webpeck.DefinePlugin({
'process_env': {
NODE_ENV: JSON.stringify('production')
}
})
]
}

架构设计

Vue的整体分为三个部分:核心代码、开平台相关和公用工具函数。

同时,其架构也是分层的,最上层是入口,最底层是普通的构造函数。在最底层与最顶层中间,我们需要逐渐增加一些方法与属性,而构造函数上一层的一些方法会最终添加到构造函数的prototype属性中,再上一层的方法最终会添加到构造函数上,这就叫做全局的API(Global API),例如常用的Vue.useVue.$set等。也就是说,先在构造函数的prototype属性中添加方法后,再向构造韩寒申诉自身添加API。再向上就是跨平台的相关内容了。在我们进行构建时,首先会选择一个平台,然后将特定于这个平台的代码添加加载到构建文件中,再上一层是渲染层,其中有两个部分,分别是服务器渲染和编译器相关内容,这部分的内容是可选的,构建时会根据构建的目标文件来选择是否需要将编译器加载进来。

最顶层的入口,其实时相对来说的,对于构建工具以及使用Vue.js的开发者来说,这是入口,而对于Vue.js自身来说,这时出口。

就整体来看,下面三层属于核心代码区域,而上面三层是属于与平台相关的代码。

这里以构建Web平台下运行的文件为例,如果我们构建的是完整版本,我们会选择Web平台的入口文件开始构建,这个文件会最终导出一个Vue构造函数,导出前回想Vue的构造函数中添加一些方法,流程如下:先将Vue构造函数的prototype属性上添加一些方法,然后向Vue构造函数自身添加一些全局的API,接着将平台特有的代码导入进来,最后将编译器导入进来,最终将所有代码通Vue构造函数仪器导出

总结

由于实习原因,更新无固定时间,这一篇就总结记录了一下大体上的整体流程以及全局的架构设计,更多的细节例如API实现以及生命周期等会记录再后续的博客中。