vue源码解析:vue生命周期方法$destory方法的实现原理
我们知道vue生命周期的最后一个阶段是销毁阶段,那么vue会调用自己的destory函数,那么$destory函数的实现原理是什么?且往下看。用法:vm.$destroy()作用:完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器。触发beforeDestroy和destroyed的钩子。源码:Vue.prototype.$destroy = function () {cons
我们知道vue生命周期的最后一个阶段是销毁阶段,那么vue会调用自己的destory函数,那么$destory函数的实现原理是什么?且往下看。
用法:
vm.$destroy()
作用:
完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器。触发 beforeDestroy
和 destroyed
的钩子。
源码:
Vue.prototype.$destroy = function () {
const vm: Component = this
if (vm._isBeingDestroyed) {
return
}
callHook(vm, 'beforeDestroy')
vm._isBeingDestroyed = true
// remove self from parent
const parent = vm.$parent
if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
remove(parent.$children, vm)
}
// teardown watchers
if (vm._watcher) {
vm._watcher.teardown()
}
let i = vm._watchers.length
while (i--) {
vm._watchers[i].teardown()
}
// remove reference from data ob
// frozen object may not have observer.
if (vm._data.__ob__) {
vm._data.__ob__.vmCount--
}
// call the last hook...
vm._isDestroyed = true
// invoke destroy hooks on current rendered tree
vm.__patch__(vm._vnode, null)
// fire destroyed hook
callHook(vm, 'destroyed')
// turn off all instance listeners.
vm.$off()
// remove __vue__ reference
if (vm.$el) {
vm.$el.__vue__ = null
}
// release circular reference (##6759)
if (vm.$vnode) {
vm.$vnode.parent = null
}
}
原理:
从代码的逻辑开始,首先会判断_isBeingDestroyed是不是true,_isBeingDestroyed为是不是处在销毁阶段的表示,如果是true则直接退出,防止反复执行销毁逻辑。接着会执行beforeDestory钩子,标志着组件正式进入到销毁阶段。
第一步,首先就是判断当前实例是否有父级实例,如果当前实例有父级实例,同时该父级实例没有被销毁并且不是抽象组件,那么就将当前实例从其父级实例的$children
属性中删除。
第二步,就是将自身的依赖追宗和事件监听移除。
依赖有俩部分:
- 实例自身依赖其他数据,需要将实例自身从其他数据的依赖列表中删除;
- 实例内的数据对其他数据的依赖(如用户使用
$watch
创建的依赖),也需要从其他数据的依赖列表中删除实例内数据。
首先执行vm._watcher.teardown()
将实例自身从其他数据的依赖列表中删除,teardown
方法的作用是从所有依赖向的Dep
列表中将自己删除。然后,在前面文章介绍initState
函数时我们知道,所有实例内的数据对其他数据的依赖都会存放在实例的_watchers
属性中,所以我们只需遍历_watchers
,将其中的每一个watcher
都调用teardown
方法,从而实现移除实例内数据对其他数据的依赖。
移除响应式数据:
给当前实例上添加_isDestroyed
属性来表示当前实例已经被销毁,同时将实例的VNode
树设置为null。然后触发destroy生命钩子函数。
第三步,调用实例的vm.$off
方法(关于该方法在后面介绍实例方法时会详细介绍),移除实例上的所有事件监听器。
最后,再移除一些相关属性的引用,至此,当前实例算是销毁完毕。
更多推荐
所有评论(0)