过程中有一些地方看不懂我就直接跳过了,死磕的话影响读下去的信心,效率也不高,整体了解一遍了再回头看,应该会更好理解点
-
src/instance/index.js
在initMixin
方法中给Vue
的原型上添加_init
方法,在Vue
的构造函数中直接调用_init
方法,在这个方法中首先初始化了mixin
(将mixin
中注册的options
与new Vue
传入的参数options
合并)涉及到的合并方法是mergeOptions
但是尤大觉得这个很浪费性能所以做了一层优化~(具体就是一顿赋值)。 -
initLifecycle
初始化生命周期(此方法在_init
中调用),找到祖宗元素(一个while
循环),然后把当前的vue
实例的一些属性初始化一下,包括$parent,$root,$ref 等等等(src/instance/lifecycle.js
) -
initEvents
初始化事件(此方法在_init
中调用) -
initRender
初始化渲染函数(此方法在_init
中调用),将_c
,$createElement
方法挂在实例上,defineReactive
(这个方法是在observer
中的他的作用是让数据变得响应化)这里响应化的是$attr
,$listeners
-
调用生命周期钩子
callHook
这里的钩子是beforeCreate
,callHook
这里应用了策略模式,声明一个空对象strats
在这个对象上挂了一个个生命周期函数的数组(比如父级的beforeCreate
和子级的beforeCreate
),这个生命周期函数挂载到实例上实际上是在第一步中的mergeOptions
中做的 -
initInjections
这个东西没怎么用过回头看看文档再来研究,他出现在响应化props
和data
之前 -
initState
这一步做的就是大家耳熟能’翔’的,数据的响应式,也是 Vue 中的核心模块,主要内容都在observer
文件夹下。这个方法首先做的就是初始化options
中的props
、methods
、data
、computed
、watch
。后面在一个一个说吧。不然也太多了,这里说一下initData
这个方法首先是拿到data
这个函数的返回值也就是我们定义的那些需要响应的数据,然后将这些数据代理到Vue
实例上,以便于我们都可以用this
访问到(这里也是用defineProperty
实现的),之后就是observe data
(用了源码中的注释)调用observe
方法,方法中判断了当前的这个属性是否是对象,判断了这个对象是不是被响应化过(通过当前对象上是否有__ob__
属性来判断),然后还有一堆判断其中还有一个Object.isExtensible
(看到这又学到了一个新方法,对象是否可扩展就是能不能在对象上添加属性)经过判断后最后会返回new Observer(value)
。Observer
这个类在初始化时创建了Dep
的实例、将__ob__
属性添加到对象上,判断是否是数组(因为数组与对象的响应化不同需要做一层函数拦截),在walk
方法中将当前对象的每一个属性都用defineReactive
函数循环了一遍(递归),这也是Vue2.0
中性能方面不好的地方,3.0
中做了很大的提升,应用Proxy
只有在某一个属性被访问的时候才会去递归响应化他,而不是像现在这样上来就一股脑的全都递归一遍。
然后就是 defineReactive
方法,这个方法一开头我又学到了一个方法 Object.getOwnPropertyDescriptor
获取属性描述器,用以判断当前的这个属性是否可配置(configurable === true
),之后就是重点了大家总说的,通过Object.defineProperty
重写这个属性,主要是重写 get
和 set
两个方法。稍微有点绕这里,在 get
方法中通过 Dep.target
来判断,是否触发dep.depend()
(这个方法是在 Dep 类的原型方法主要是作用是调用 Dep.target
上的 addDep
方法,将当前的 Dep
实例存放在 target
上,target
实际上就是当前的 watcher
实例,同时也将当前的这个 watcher
存放在 dep
的 subs
中),set
中其他的先不看,核心就这一句 dep.notify()
,上面说了 dep
中存放了 watcher
,这里就是将 dep
中存的每一个 watcher
都调用一遍(渲染的话只有一个渲染watcher
)。乱七八糟的说了一堆watcher
那么 watcher
是从什么时候初始化的呢?是这样的一个方法mountComponent
可以理解为咱们用的$mount
,Vue
默认会在渲染的过程中直接创建一个渲染 watcher
,这个 watcher
里面东西特别多,先捡初始化的部分说(就是我能看懂的地方)
通过调用pushTarget
将当前的 watcher
实例赋值给 Dep.target
,然后调用实例化 watcher
时传入的更新方法 updateComponent
也就是 vm._update()
这个方法是用于渲染的,渲染的过程中肯定会读取 data
中的数据,这时就会触发了当前读取数据的 get
方法,而此时的 Dep.target
是当前的这个 watcher
,这时就是上面的将 dep
存到 watcher
的 deps
中,将 watcher
存放到 dep
的 subs
中,这也是一个收集依赖的过程 然后 set
的时候调用的方法就会触发更新触发更新的过程中就会有 nextTick
的逻辑
预知后事如何请看下回分解,今天眼睛太累了。不写了,估计一般人也看不下去这篇文章,我也是对着源码写的,看的话建议你也对着源码看。