Vue源码MVVM核心精读,如何为?
摘要:要写 Vue.js 的源码分析,可以写一个系列。但是大体上,都知道了 Vue.js 的核心有那些东西。最重要,莫过于依赖收集了。在开始之前,这篇文章要回答如下几个问题。 PS: 内容有点长,看核心部分即可。而核心问题,看看下面的 QA。 V
要写 Vue.js 的源码分析,可以写一个系列。但是大体上,都知道了 Vue.js 的核心有那些东西。最重要,莫过于依赖收集了。在开始之前,这篇文章要回答如下几个问题。
PS: 内容有点长,看核心部分即可。而核心问题,看看下面的 QA。
Vue 是什么?
Vue 是 JavaScript 的一款 MVVC 框架,从2014年由作者 Evan You 推出以来以简单易上手著称,搭配 options object style API 和易于理解的文档。在国内外迅速收到了一大片 star,成为了 GitHub 社区的明星项目。
其组成部分如下:
MVVM = Observer + Dep + Watcher
VirtualDOM = (VNode = instance.render()) + Update(Patch(diff(newVNode, oldVNode)))
Component<functional|abstract|class|HOC> = new Vue(ComponentOptions) + VirtualDOM
ComponentOptions = name + filters + mixins + filters + components + props + data + computed + watch + provide + inject + methods + LifeCycle + template/render
Vue.compile/vue-template-compiler - 模版编译
什么是 MVVM 以及 Vue 如何实现 MVVM?
Model-View-ViewModel 是一种软件架构,我的理解是 MVC/P(Model-View-Controller)的进化版。
从分层的角度去看,最上层是 View,中间层是 Controller/Presenter/ViewModel, 最下层就是 Model。
Model 声明数据模型,View 声明视图,ViewModel 声明视图与数据模型之间的绑定关系。
当 Model 更新时 ViewModel 也被框架随之更新。这样做的好处是进一步解藕,将数据与视图的绑定关系抽象成 ViewModel 的 directives。通过对 Model 的赋值更新 View ,而无需手动编写 controller 更新 view。
Vue 通过数据劫持实现 MVVM 架构。其核心是 Observer、Dep 和 Watcher 三个构造函数。component options 声明中的 data 即 reactive object 就是 Model,而 template 就是 View,其中的指令 v-bind , v-for 等就是 ViewModel 的绑定关系的实现。
Vue 如何实现依赖收集?
主要基于 Observer, Dep, Watcher 三个对象实现:
Observer 观察者:在 Vue2 的 option API 模式中,使用 Observer(观察者,基于 ES5 的 Object.defineProperty API 实现)生成响应式对象(Reactive Object),拦截对象每个 key 的 getter/setter 植入 dep.depend() / dep.notify() 即 Sub/Pub。
Dep 依赖管理: Observer 跟 Watcher 的 依赖关系 的 动态收集器。
Watcher 订阅者: 在 Watcher.prototype.get() 中 pushTarget(this) 指定 Dep.target 并调用 this.getter 订阅所有的 deps 依赖关系,并在 setter() -> dep.notify() 后执行所有 deps 中 watcher 的 update() 更新依赖。
当访问响应式对象属性时,会进入 getter 劫持函数的逻辑。
1. 如果存在有效的 Dep.target(即当前收集依赖的 watcher),
2. 调用 watcher.addDep(dep) 收集当前属性的 dep 对象作为 watcher 的依赖,
3. 同时执行 dep.addSub(this) 收集 watcher 作为 dep 的 subscribes 订阅者。
当对响应式对象的属性赋值时,会进入 setter 劫持函数的逻辑。
