对vue.js 生命流程大致总结
Posted 前端教程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对vue.js 生命流程大致总结相关的知识,希望对你有一定的参考价值。
首先安利一波福利,有没有用vscode的小伙伴?推荐一个神奇的字体,自从用了这个字体,敲代码效率简直上天了。先上图看看效果:
全等
箭头函数
小于等于
还有其他许多,就不一一列举出来了。
有没有看上了的?
没有我等下再来问。
在这篇文章里我将是这几个月来对 Vue 学习的一个小结。
思路
Vue 和其他的 MVVM 思路是类似的:
主要是为了实现三个过程:
Observer: 通过Observer对data进行监听,并且提供订阅某个数据项的变化的能力。利用
Object.defineProperty
, 将data里的每个属性全部转化为getter/setter,已遍拦截对象赋值与取值操作;Compiler: 将template 解析为 render()方法;
watcher: Compiler 的解析结果与 Observer 结合起来,在 Observer 监听到数据发生改变时,接受通知,进而触发 re-render, 重新渲染DOM。
new Vue
我们从 new Vue
开始,
上图即是官网给出的一张生命周期图,主要是四个过程:
create: 在 new Vue() 时会运行,创建出 Vue 对象。
mount: 会根据 el, template, render 等,生成 Vnode, 完成 diff 算法后挂载到 DOM 上。
updata: 当数据发生改变时,会重新渲染 DOM。
destory: Vue 销毁时会运行。
现在,我们进入源码,分析具体的实现:
Create: 首先运行
new vue()
的时候,会进入_init...,
其中关键部分的代码如下:
可以看出在 beforeCreate
与 created
只有initState
, initState
是用于实现data observer
和 event/watcher
。
Mount: 在
_init
最后,会运行vm.$mount
方法:
具体 vm.$mount
的分析,请看上篇...。最后进行了 render()
, 从而会有Vnode
, 经过 DIFF 算法后会有真实 DOM ;
Update: DOM 之后,会进行update方法:
vm._watcher = new Watcher(vm, () => { vm._update(vm._render(), hydrating) }, noop)
将以上用一张序列图表示也就是:
深入响应式原理 (Observer, watcher)
MVVM 框架有一个很重要的特征:就是当数据放生变化后,会自动更新对应的DOM节点。 Vue 是怎么实现的?
以上是来自官网的一张图。
前面提到在 beforeCreate
与 created
两个生命周期钩子函数之间会运行 initState()
方法。
initState()... 源码里:
在这个方法里,会对props, data, computed
等属性利用 Object.defineProperty
将这些属性全部转化为 getter/setter
。
我们以 initData()
为例子进行分析:
这里有一个值得注意的地方,
proxy(vm, "_data", keys[i])
, 设置vm._data
为代理,具体作用是实现vm.a === vm._data.a
。
在 initData()
最后 会进行 observe(data, this)
。
在observe()...里,既是转化为 getter/setter
。
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true, get: function reactiveGetter () { const value = getter ? getter.call(obj) : val // 只有在有Dep.target时才说明是Vue内部依赖收集过程触发的getter
// 那么这个时候就需要执行dep.depend(),将watcher(Dep.target的实际值)添加到dep的subs数组中
// 对于其他时候,比如dom事件回调函数中访问这个变量导致触发的getter并不需要执行依赖收集,直接返回value即可
if (Dep.target) {
dep.depend() if (childOb) { // 如果value在observe过程中生成了ob实例,那么就让ob的dep也收集依赖
childOb.dep.depend()
} if (isArray(value)) { //如果数组元素也是对象,那么他们observe过程也生成了ob实例
dependArray(value)
}
} return value
}, set: function reactiveSetter (newVal) { var value = getter ? getter.call(obj) : val if (newVal === value) { return
} if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
} // observe 这个新数据
childOb = observe(newVal) // 通知到dep 进行数据更新。
dep.notify()
}
})
到这个时候,Observer 监听已经完成,如果数据更新,我们会进行 dep.notify()
方法:
dep.notify()... , 方法里会执行update()
:
update()... , 中会进行queueWatcher()
方法:
queueWatcher()
, 目的是通过 nextTicker
来执行 run()
:
在 run()
里,其实就是执行 this.get()
方法:
在 get()
方法里,会运行 this.getter()
, 方法来更新 DOM 。
this.getter()
方法是啥?
再就是上文中所提到的new Watcher(), 的第二个参数。
vm._watcher = new Watcher(vm, () => { vm._update(vm._render(), hydrating)
}, noop)
而在 new Watcher
构造完成后,会调用 this.get()
,触发 this.getter()
,方法触发 DOM 更新。
具体可以看watcher.js...:
截一个关键代码部分的图:
以上,用一张序列图来表示,既就是:
对以上总结:
首先
_init
,对属性利用Object.defineProperty
,将属性转为getter/setter
,在setter
方法里,会调用dep.notify()
。对
vm
设置new Watcher
。data
变化时,进行数据跟新。
原文:https://jkchao.cn/article/59d6e93c7e2ee06d412efef9
推荐资料:
1.
2.
觉得本文对你有帮助?请分享给更多人
关注「前端教程」,提升前端技能
以上是关于对vue.js 生命流程大致总结的主要内容,如果未能解决你的问题,请参考以下文章