vue.js源码分析

159 阅读3分钟

1. 描述 Vue 响应式原理。

基本概念

data

vue实例中的数据项

observer

数据属性的观察者,监控对象的读写操作。

dep

(dependence的缩写),字面意思是“依赖”,扮演角色是消息订阅器,拥有收集订阅者、发布更新的功能。

watcher

消息订阅者,可以订阅dep,之后接受dep发布的更新并执行对应视图或者表达式的更新。

dep和watcher

dep和watcher的关系,可以理解为:dep是报纸,watcher是订阅了报纸的人,如果他们建立了订阅 的关系,那么每当报纸有更新的时候,就会通知对应的订阅者们。

view

暂且认为就是在浏览器中显示的dom(关于virtual dom的内容暂时不在本文讨论)

收集依赖

watcher在自身属性中添加dep的行为,后面会详细介绍

收集订阅者

dep在自身属性中添加watcher的行为,后面会详细介绍

响应式原理

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。 这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。 每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

描述 Vue 响应式原理中的 Vue 类、Observer 类、Dep 类、Watcher 类、Compiler 类。

Vue类

  • 接收配置信息
  • 将 data 的属性转换成 Getter、Setter,并注入到 Vue 实例中。
  • 监听 data 中所有属性的变化,设置成响应式数据
  • 调用解析功能(解析模板内的插值表达式、指令等)

Observer 类

  • 通过数据劫持方式监视 data 中的属性变化,变化时通知消息中心 Dep。
  • 需要考虑 data 的属性也可能为对象,也要转换成响应式数据

Dep类

Dep 是 Dependency 的简写,含义为“依赖”,指的是 Dep 用于 收集与管理订阅者与发布者之间的依赖关系。

  • 为每个数据收集对应的依赖,存储依赖。
  • 添加并存储订阅者。
  • 数据变化时,通知所有观察者

Watcher 类

  • 实例化 Watch 时,往dep对象中添加自己
  • 当数据变化触发 dep, dep 通知所有对应的 Watcher 实例更新视图。

Compiler 类

  • 进行编译模板,并解析内部指令与插值表达式。
  • 进行页面的首次渲染
  • 数据变化后,重新渲染视图

什么是 Virtural DOM。

Virtual DOM(虚拟 DOM),是由普通的 JS 对象来描述 DOM 对象

{
    sel: "div",
    data: {},
    children: undefined,
    text: "Hollo Virtual DOM",
    elm: undefined,
    key: undefined
}

Snabbdom 的使用流程

安装 Snabbdom

  • npm intall snabbdom@2.1.0

导入 Snabbdom

  • Snabbdom 的两个核心函数 init 和 h()
  • init() 是一个高阶函数,返回 patch()
  • h() 返回虚拟节点 VNode

Snabbdom 的核心介绍

  • init() 设置模块,创建 patch() 函数
  • 使用 h() 函数创建 JavaScript 对象(VNode)描述真实 DOM
  • patch() 比较新旧两个 VNode
  • 把变化的内容更新到真实 DOM 树