Vue.js 源码剖析-响应式原理、虚拟 DOM、模板编译和组件化

3-2

vue的不同构建版本

npm run build

版本 umd CommonJS ESModule
未压缩版本 Full(完整版) vue.js vue.common.js vue.esm.js
未压缩版本 Runtime-only(运行时版) vue.runtime.js vue.runtime.common.js vue.runtime.esm.js
压缩版本 Full(production) vue.min.js
压缩版本 Runtime-only(production) vue.runtime.min.js
  • 完整版:同时办函编译器和运行时版本
  • 编译器:用来将模板字符串便已成为JavaScript渲染函数的代码,体积大,效率低
  • 运行时:用来创建vue实例、渲染并处理虚拟DOM等的代码,体积小,效率高,基本上就是出去编译器的代码
  • UMD:UMD版本通用的模块版本,支持多种模块方式,vue.js默认文件就是运行时+编译器的UMD版本
  • CommonJS(cjs):CommonJS版本用来配合老的打包工具比如Browserify或webpack1
  • ESModule:从2.6开始Vue会提供两个ESModules(ESM)构建稳健,为现代打包工具提供的版本
    • ESM格式被设计为可以被静态分析,所以打包工具可以利用这一点来进行tree-shaking并将用不到的代码排除出最终包

使用vue-cli创建的项目默认导入的是运行时版本并且是ESM模块化方式

阅读源码

  • el不能是body或者html标签
  • 如果沒有render,把template转换成render函数
  • 如果有render方法,直接调用mount挂载DOM

VUE

四个导出Vue的模块

  • src/platforms/web/entry-runtime-with-compiler.js
    • web平台相关入口
    • 重写了平台相关的$mount()方法
    • 注册了Vue.compile()方法,传递一个HTMl字符串返回render函数
  • src/platforms/web/runtime/index.js
    • web平台相关
    • 注册和平台相关的全局指令:v-model、v-show
    • 注册和平台相关的全局组件:v-transition、v-transition-group
    • 全局方法:
      • patch:把虚拟DOM转换成真实DOM
      • $mount:挂载方法
  • src/core/index.js
    • 与平台无关
    • 设置了Vue的静态方法,initGlobalAPI(Vue)
  • src/core/instance/index.js
    • 与平台无关
    • 定义了构造函数,调用了this_init(options)方法
    • 给Vue混入了常用的实例成员

数据响应式原理

核心: 把会改变数组的方法进行修补,当这些方法被调用的时候调用notify方法,遍历数组中的元素,把对象元素进行响应式处理

Watcher类

Watcher分为三类,Computed Watcher, 用户Watcher(监听器),渲染Watcher

  • 渲染Watcher的创建时机
    • /src/core/instance/lifeycle.js

vm.$delete

  • 功能
    删除对象的属性,如果对象是响应式,确保删除能c触发更新视图,这个方式主要用于避开Vue不能检测到属性被删除的限制,,目标对象不能是一个Vue实例或Vue实例的根数据对象

vm.$watch(expOrFn, callback, [options])

  • 功能
    观察Vue实例变化的一个表达式或计算属性函数,回调函数得到的参数为新值和旧值,表达式只接受监督的键路径,对于更复杂的表达式,用一个函数取代
  • 参数
    • expOrFn: 要监视的$data中的属性,可以是表达式或函数
    • callback: 数据变化后执行的函数
      • 函数: 回调函数
      • 对象: 具有handle属性(字符串或函数),如果该属性为字符串则methods中相应的定义
    • options:
      • deep: 布尔类型,深度监听
      • immediate: 布尔类型,是否立即执行一次回调函数

三种类型的Watcher对象

  • 没有静态方法,因为$watch方法中要使用vue实例
  • Watcher分为三种:计算属性Watcher,用户Watcher(侦听器),渲染Watcher
    • 创建顺序:计算属性Watcher,用户Watcher,渲染Watcher
  • vm.$watcher

nextTick()

  • Vue更新DOM是异步执行的,是批量的
    • 在下次DOM更新循环结束之后执行延迟回调,在修改数据之后立即使用这个方法,获取更新后的DOM
    • vm.$nextTick()

虚拟DOM

  • 虚拟DOM(VirtualDOM)是使用JavaScript对象来描述真实DOM
  • Vue中的虚拟DOM借鉴了Snabbdom,并添加了Vue的特性,例如指令和组件机制
  • 使用虚拟DOM可以避免直接操作DOM,提高开发效率
  • 虚拟DOM作为一个中间层可以跨平台
  • 虚拟DOM不一定能提高性能
    • 首次渲染会增加开销
    • 复杂视图情况下提高渲染性能

h函数

  • vm.$createElement(tag, data, children, normalizeChildren)
    • tag:标签名称或组件对象
    • data:描述tag,可以设置dom的属性或标签的属性
    • children:tag中的文本节点或子节点
  • h函数返回的是一个VNode对象,也就是虚拟DOM
  • VNode核心属性
    • tag 调用h函数传入的tag
    • data 调用h函数传入的data
    • children 调用h函数传入的children
    • elm VNode转换为真实DOM会记录到elm的属性中
    • key 复用当前元素

模板编译

模板编译的主要目的是将模板转换为渲染函数

  • Vue 2.x使用VNode描述视图以及各种交互,用户自己编写VNode比较复杂
  • 用户只需要编写类似HTML的代码-Vue.js模板,通过编译器将模板转换为返回VNode的render函数
  • .vue文件会被webpack在构建过程中转换成render函数

抽象语法树

  • 抽象语法树建成AST(Abstract Syntax Tree)
  • 使用对象的形式描述树形的代码结构
  • 此处的抽象语法是用来描述树形结构的HTML字符串
  • 模板字符串转换为AST后,可以通过AST对模板做优化处理
  • 标记模板中的静态内容,在patch的时候直接跳过静态内容
  • 在patch的过程中静态内容不需要对比和重新渲染

Vue组件

  • 一个Vue组件就是一个拥有预定义选项的一个Vue实例
  • 一个组件可以组成页面上一个功能完备的区域,组件可以包含脚本、样式、模板
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容