尝试总结一下Vue的响应式机制。主要是core/observer里面的代码。如果能把这些代码抽出来实现一个自己的简单的响应式就好了,目标是一个能够监听数据变化的小型demo框架,监听后把事件暴露出来,具体要做什么让监听回调函数去做,并不包括在响应式系统中。
从入口文件中规中矩的开始吧
core/observer/index.js
这个文件导出了五个内容:
- Observer
- observe
- defineReactive
- set
- del
Observer
这个类是响应式顶重要的类了吧。从名字上也能看出来,这是监听者。设计模式中就有这一个模式,监听者模式,四人帮的设计模式中文版里叫观察者模式,叫啥都一样,能理解意思就行吧,嘻嘻。或许观察者更贴切,那监听者这个词啥咋到我脑子里的,哎,还是不免要想想:(
Observer的注释已经很能说明它的用途了
/**
* Observer class that is attached to each observed
* object. Once attached, the observer converts the target
* object's property keys into getter/setters that
* collect dependencies and dispatch updates.
*/
响应式系统涉及的类还是很多的,看来还是有可能画一个类之间的交互图的。
to be continue
读着读着,我发现响应式不只在core/observer中,它还散落在别得文件里,比如core/global-api/extend.js会有,这里面其实是使用响应式的地方。
还是把响应式的内容分开来写吧,一篇文章写不完。这篇只写大体过程,子篇写实现细节,这样可能比较好。
大致过程
我们都知道响应式(reactive)的的含义,大体可以这样说,数据改变了,依赖数据的视图会自动改变。这大概就是响应式了,达到了数据驱动的目的,让我们不再聚焦视图的修改。
那么Vue是怎么做到的呢?
这里要抛出几个类,它们是参与响应式的主角。
- Observer
- Dep
- Watcher
它们的关系是怎样的呢?
在我看来Observer跟Dep和Watcher没有直接关系,响应式主要应该是由Dep和Watcher来完成的,它俩才是核心。
Dep是在调用defineReactive时创建的,会形成一个闭包。在这个闭包内会调用defineProperty来定义对象的属性。Vue的响应式就是基于defineProperty来实现的,而defineProperty是ES5才出现的,而且是不能模拟的,因此不支持ES5的浏览器上是不能运行Vue的,这就包括IE8及以下版本。
继续说回defineProperty,它定义了get和set。在get里面,会把上面说的Dep实例跟当前的Watcher实例绑定,dep.depend()的调用。而在set里面会调用dep.notify来通知跟Dep实例相关的Watcher实例来进行update。
总结下来,Dep实例是跟对象的属性的get和set关联的,而Watcher实例是跟更新操作关联的,因为在创建Watcher实例是都是要求传入一个cb的,这个cb就会做一些更新操作。
描述一下响应式触发的过程。
setter -> dep.notify -> watcher.update -> cb()
说一下Watcher是怎么跟视图的刷新关联上的呢,从上面的内容可以知道,视图的刷新一定是放在了cb里咯。很可惜,错了!!:(具体还是看下面watcher的文章吧
- Watcher
- Dep
- Observer
本文还会慢慢完善的
有用请点赞,嘻嘻:)