Vue源码学习一

Vue

程序结构

此处输入图片的描述
Vue.js 是一个非常典型的 MVVM 的程序结构,整个程序从最上层大概分为

全局设计:包括全局接口、默认选项等
vm 实例设计:包括接口设计 (vm 原型)、实例初始化过程设计 (vm 构造函数)
这里面大部分内容可以直接跟 Vue.js 的官方 API 参考文档对应起来,但文档里面没有且值得一提的是构造函数的设计,下面是我摘出的构造函数最核心的工作内容

此处输入图片的描述
整个实例初始化的过程中,重中之重就是把数据 (Model) 和视图 (View) 建立起关联关系。Vue.js 和诸多 MVVM 的思路是类似的,主要做了三件事:

  • 通过 observer 对 data 进行了监听,并且提供订阅某个数据项的变化的能力
  • 把 template 解析成一段 document fragment,然后解析其中的 directive,得到每一个 directive 所依赖的数据项及其更新方法。比如 v-text=”message” 被解析之后 (这里仅作示意,实际程序逻辑会更严谨而复杂)
  • 通过 watcher 把上述两部分结合起来,即把 directive 中的数据依赖订阅在对应数据的 observer 上,这样当数据变化的时候,就会触发 observer,进而触发相关依赖对应的视图更新方法,最后达到模板原本的关联效果。

所以整个 vm 的核心,就是如何实现 observer, directive (parser), watcher 这三样东西

编译流程

此处输入图片的描述

模板解析过程

相关源码
将template解析为AST(抽象语法树)

AST

  • 节点类型有三种: ASTElement:tag标签、ASTText:纯文本、ASTExpression: 表达式
  • eg:
declare type ASTNode = ASTElement | ASTText | ASTExpression;

declare type ASTElement = {
  type: 1;
  tag: string;
  attrsList: Array<{ name: string; value: string }>;
  attrsMap: { [key: string]: string | null };
  parent: ASTElement | void;
  children: Array<ASTNode>;
  static?: boolean; // 静态节点标记
  ……
}

此处输入图片的描述

compile() 函数

再来看 compile() 函数,这里是实现模板解析的核心,来做文件 src/compiler/index.js,基本逻辑为:

 // 参数:template, options
ast = parse(template.trim(), options)
optimize(ast, options)
code = generate(ast, options)
return {
  ast,
  render: code.render,
  staticRenderFns: code.staticRenderFns
}

逻辑很清晰,首先从模板进行解析得到抽象语法树(ast),进行优化,最后生成结果代码。整个过程中肯定会涉及到 Vue 的语法,包括指令、组件嵌套等等,不仅仅是得到构建 Virtual DOM 的代码。

需要注意的是,编译得到 render 其实是代码文本,通过 new Function(code) 的方式转为函数

Vue数据绑定图解

此处输入图片的描述

diff

参考Vue原理解析之Virtual Dom

Vue运行机制小结

  • 文本模板,编译得到生成 vnode 的函数(render),该过程中会识别并记录 Vue 的指令和其他语法
  • new Vue() 得到 vm 对象,其中传入的数据会进行数据劫持处理,从而可以收集依赖,实现数据绑定
  • 渲染过程是将所有数据交由渲染函数(render)进行调用得到 vnode,应该 Virtual DOM 的机制实现初始渲染和更新
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章