阅读 163

Vue源码,你真的看懂了吗(一)

前言

写这个系列主要是记录自己在学习vue源码的一些整理和感悟,文章不会超级详细,也不会一直跟随源码的脚步进行更新,只会抽取出比较重要核心的部分,同时也相当于是自己的学习笔记,方便以后复习查阅。

如果有错误或者疑问也可以在下方评论。就酱!੧ᐛ੭

目录

  • 项目结构和架构设计
  • 响应式原理
    • 操作:变化侦测
    • 结果:数据驱动视图
  • 虚拟DOM
    • patch函数与diff算法
  • 模版编译
    • 解析器、优化器、代码生成器
  • Vue构造函数
    • 原型方法
    • 静态属性和方法(全局API)
  • Vue生命周期
    • 生命周期各个阶段
    • 初始化状态
  • Vue中的优化策略

Vue.js简介

Vue 是一套用于构建用户界面的渐进式框架。

所谓渐进式框架,就是把框架分层,使项目变得更加清晰、便于维护,同时也增加了灵活性,能够适应不同大小的应用需求。 最核心的部分是视图层渲染,然后往外是组件机制,在这个基础上再加入路由机制(Router),再加入状态管理(Vuex),最外层是构建工具(vue-cli)。

以往我们在页面中直接操作DOM节点是属于命令式操作,而在Vue中,我们通过描述状态和DOM之间的映射关系,就可以将状态渲染成DOM呈现在用户界面中,也就是渲染到网页上,这是属于声明式操作DOM。

小结:

  • 渐进式框架
  • 声明式操作DOM

项目结构和架构设计

项目结构

├── scripts ------------------------------- 与构建相关的脚本和配置文件,一般情况下我们不需要动
├── dist ---------------------------------- 构建后文件的输出目录
├── examples ------------------------------ 存放一些使用Vue开发的应用案例
├── flow ---------------------------------- flow类型声明,使用开源项目 [Flow](https://flowtype.org/)
├── packages ------------------------------ 存放独立发布的包的目录
├── test ---------------------------------- 包含所有测试文件

// important
├── ** src ** ----------------------------------- 这个是我们最应该关注的目录,包含了源码
│   ├── ** compiler ** -------------------------- 编译器代码的存放目录,将 template 编译为 render 函数,模版编译相关代码
│   ├── ** core ** ------------------------------ 通用的核心代码,与平台无关的运行时代码
│   │   ├── ** observer ** ---------------------- 响应系统,包含数据观测的核心代码
│   │   ├── ** vdom ** -------------------------- 包含虚拟DOM创建(creation)和打补丁(patching)的代码
│   │   ├── ** instance ** ---------------------- 包含Vue构造函数设计相关的代码
│   │   ├── ** global-api ** -------------------- 包含给Vue构造函数挂载全局方法(静态方法)或属性的代码
│   │   ├── components -------------------- 包含抽象出来的通用组件
│   ├── ** server ** ---------------------------- 包含服务端渲染(server-side rendering)的相关代码
│   ├──** platforms ** ------------------------- 包含平台特有的相关代码,不同平台的不同构建的入口文件也在这里
│   │   ├── web --------------------------- web平台
│   │   │   ├── entry-runtime.js ---------- 运行时构建的入口,不包含模板(template)到render函数的编译器,所以不支持 `template` 选项,我们使用vue默认导出的就是这个运行时的版本。
│   │   │   ├── entry-runtime-with-compiler.js -- 独立构建版本的入口,它在 entry-runtime 的基础上添加了模板(template)到render函数的编译器
│   │   │   ├── entry-compiler.js --------- vue-template-compiler 包的入口文件
│   │   │   ├── entry-server-renderer.js -- vue-server-renderer 包的入口文件
│   │   │   ├── entry-server-basic-renderer.js -- 输出 packages/vue-server-renderer/basic.js 文件
│   │   ├── weex -------------------------- 混合应用
│   ├── ** sfc ** ------------------------------- 包含单文件组件(.vue文件)的解析逻辑,用于vue-template-compiler包
│   ├── ** shared ** ---------------------------- 包含整个项目的公用工具代码

├── types --------------------------------- Typescript类型定义
│   ├── test ------------------------------ 类型定义测试
├── package.json -------------------------- 定义了这个项目所需要的各种模块,以及项目的配置信息
├── yarn.lock ----------------------------- yarn 锁定文件
├── .editorconfig ------------------------- 针对编辑器的编码风格配置文件
├── .flowconfig --------------------------- flow 的配置文件
├── .babelrc ------------------------------ babel 配置文件
├── .eslintrc ----------------------------- eslint 配置文件
├── .eslintignore ------------------------- eslint 忽略配置
├── .gitignore ---------------------------- git 忽略配置
复制代码

不同Vue.js构建版本的区别

  • 编译器 Compiler:负责将 template 编译为 render 函数。

  • 运行时:负责创建vue.js实例,渲染视图和使用虚拟DOM进行重新渲染。

  • 完整版: 运行时版 + Compiler = 完整版

将字符串模板编译为 render 函数的这个过程在构建的时候就可以完成,这样真正运行的代码就免去了这样一个步骤,提升了性能。同时,将 Compiler 抽离为单独的包,还减小了库的体积。

完整版的作用就是允许你在代码运行的时候去现场编译模板,在不配合构建工具的情况下可以直接使用,但是更多的时候推荐你配合构建工具使用运行时版本。

输出不同形式的模块的包

umd 是使得你可以直接使用 <script> 标签引用Vue的模块形式。

但我们使用 Vue 的时候更多的是结合构建工具,比如 webpack 之类的,cjs 形式的模块就是为 browserify 和 webpack 1 提供的,他们在加载模块的时候不能直接加载 ES Module。

webpack2+ 以及 Rollup 可以直接加载 ES Module,所以就有了 es 形式的模块输出。

架构设计

Vue.js整体结构分为三个部分:核心代码跨平台相关公用工具函数

核心代码包含原型方法和全局API,它们可以在各个平台下运行,而跨平台相关部分更多的是与渲染有关的功能,不同平台下渲染API是不同的。

以构建Web平台下运行的文件为例,如果构建的是完整版本,就会选择Web平台的入口开始构建。首先向Vue构造函数的prototype属性上添加一些方法,接着向Vue构造函数自身添加一些全局API,再接着将平台特有的代码导入进来,最后将编译器导入进来,最终将所有的代码同Vue构造函数一起导出去。

参考

《深入浅出Vue.js》 刘博文著

vue技术内幕: caibaojian.com/vue-design/…

vue.js源码: github.com/vuejs/vue

文章分类
前端
文章标签