You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
initLifecycle(vm)initEvents(vm)initRender(vm)callHook(vm,'beforeCreate')initInjections(vm)// resolve injections before data/propsinitState(vm)nitProvide(vm)// resolve provide after data/propscallHook(vm,'created')
Vue.prototype.$destroy=function(){constvm: Component=thisif(vm._isBeingDestroyed){return}callHook(vm,'beforeDestroy')vm._isBeingDestroyed=true// remove self from parentconstparent=vm.$parentif(parent&&!parent._isBeingDestroyed&&!vm.$options.abstract){remove(parent.$children,vm)}// teardown watchersif(vm._watcher){vm._watcher.teardown()}leti=vm._watchers.lengthwhile(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 treevm.__patch__(vm._vnode,null)// fire destroyed hookcallHook(vm,'destroyed')// turn off all instance listeners.vm.$off()// remove __vue__ referenceif(vm.$el){vm.$el.__vue__=null}// release circular reference (#6759)if(vm.$vnode){vm.$vnode.parent=null}}}
可以看到,destroy步骤如下:
remove(parent.$children, vm)从父节点中先移除自己
vm._watcher.teardown() 销毁watchers
vm._data.__ob__.vmCount-- 从数据ob中删除引用
vm.__patch__(vm._vnode, null) 调用当前渲染树上的销毁钩子
callHook(vm, 'destroyed') 调用destroyed钩子
vm.$off()销毁事件监听 ...
到这里差不多就执行完了销毁任务,从而触发了destroyed钩子
一些警告
不要在选项属性或回调上使用箭头函数,比如 created: () => console.log(this.a) 或 vm.$watch('a', newValue => this.myMethod())。因为箭头函数是和父级上下文绑定在一起的,this 不会是如你所预期的 Vue 实例,经常导致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。
我们可以看一下Vue是如何执行生命周期函数的:
关于生命周期的源码执行
首先我们先来看一张官网的图:
然后我们来看一下源码里什么时候开始执行各个生命周期的:
1. beforeCreate、created
beforeCreate
和created
钩子在core/instance/init.js
的_init
方法中执行这里主要是初始化一些vm的属性,
initState
主要为定义的data
属性进行obsever
以及处理一些props
、watch
和computed
:2. beforMounted
在执行
beforMounted
的钩子的时候,会进行几部判断:1. 判断存不存在
$el
属性2. 判断存不存在
template
属性:3. mounted
这一步主要是经过了
render --> VNode --> path
步骤后生成了一个真实的dom
节点,并挂载到el
上:4. beforeUpdate
当我们执行dom更新之前,且已经经过
mounted
。会触发的钩子:5. updated
这个钩子函数主要是在异步更新队列中执行,也就是
nextTick
更新dom后会执行的钩子关于什么是
nextTick
?以及Event loop
相关知识,有兴趣可以参考我的这两篇文章:Vue nextTick 机制
Event loop 简介
6. beforeDestroy destroyed
当
$destroy
函数被调用时,会首先触发beforeDestroy
钩子:可以看到,
destroy
步骤如下:remove(parent.$children, vm)
从父节点中先移除自己vm._watcher.teardown()
销毁watchersvm._data.__ob__.vmCount--
从数据ob中删除引用vm.__patch__(vm._vnode, null)
调用当前渲染树上的销毁钩子callHook(vm, 'destroyed')
调用destroyed
钩子vm.$off()
销毁事件监听 ...到这里差不多就执行完了销毁任务,从而触发了
destroyed
钩子一些警告
比如我们执行
beforeCreate
钩子:callHook(vm, 'beforeCreate')
。因为是箭头函数,所以可以先了解箭头函数的几个特性:说到这里,应该明白了为什么不要在选项属性或回调上使用箭头函数了吧...
The text was updated successfully, but these errors were encountered: