生命周期
正常的生命周期
const onBeforeMount = createHook('bm')
const onMounted = createHook('m')
const onBeforeUpdate = createHook('bu')
const onUpdated = createHook('u')
const onBeforeUnmount = createHook('bum')
const onUnmounted = createHook('um')
const onRenderTriggered = createHook('rtg')
const onRenderTracked = createHook('rtc')
const onErrorCaptured = (hook, target = currentInstance) => {
injectHook('ec', hook, target)
}
function createHook(lifecycle) {
return function (hook, target = currentInstance) {
injectHook(lifecycle, hook, target)
}
}
function injectHook(type, hook, target = currentInstance, prepend = false) {
const hooks = target[type] || (target[type] = [])
const wrappedHook = hook.__weh || (hook.__weh = (...args) => {
if (target.isUnmounted) return
pauseTracking()
setCurrentInstance(target)
const res = callWithAsyncErrorHandling(hook, target, type, args)
setCurrnetInstance(null)
resetTracking()
return res
})
if (prepend) {
hooks.unshift(wrappedHook)
} else {
hook.push(wrappedHook)
}
}
const setupRenderEffect = (instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized) => {
instance.update = effect(function componentEffect() {
if (!instance.isMounted) {
const { bm, m } = instance
const subTree = (instance.subTree = renderComponentRoot(instance))
if (bm) {
invokeArrayFus(bm)
}
patch(null, subTree, container, anchor, instance, parentSuspense, isSVG)
initialVNode.el = subTree.el
if (m) {
queuePostRenderEffect(m, parentSuspense)
}
instance.isMounted = true
}
else {
let { next, vnode, bu, u } = instance
if (next) {
updateComponentPreRender(instance, next, optimized)
} else {
next = vnode
}
const nextTree = renderComponentRoot(instance)
const prevTree = instance.subTree
instance.subTree = nextTREE
if (bu) {
invokeArrayFns(bu)
}
patch(prevTree, nextTree,
hostParentNode(prevTree.el),
getNextHostNode(prevTree), instance, parentSuspense, isSVG)
next.el = nextTree.el
if (u) {
queuePostRenderEffect(u, parentSuspense)
}
}
}, prodEffectOptions)
}
const unmountComponent = (instance, parentSuspense, doRemove) => {
const { bum, effects, update, subTree, um } = instance
if (bum) {
invokeArrayFns(bum)
}
if (effects) {
for (let i = 0; i < effects.length; i++) {
stop(effects[i])
}
}
if (update) {
stop(update)
unmount(subTree, instance, parentSuspense, doRemove)
}
if (um) {
queuePostRenderEffect(um, parentSuspense)
}
}
捕获后代组件错误的生命周期
function handleError(err, instance, type) {
const contextVNode = instance ? instance.vnode : null
if (instance) {
let cur = instance.parent
const exposedInstance = instance.proxy
const errorInfo = (process.env.NODE_ENV !== 'production') ? ErrorTypeStrings[type] : type
while (cur) {
const errorCapturedHooks = cur.ec
if (errorCapturedHooks) {
for (let i = 0; i < errorCapturedHooks.length; i++) {
if (errorCapturedHooks[i](err, exposedInstance, errorInfo)) return
}
}
cur = cur.parent
}
}
logError(err, type, contextVNode)
}
开发环境下调试的生命周期
function createDevEffectOptions(instance) {
return {
scheduler: queueJob,
onTrack: instance.rtc ? e => invokeArrayFns(instance.rtc, e) : void 0,
onTrigger: instance.rtg ? e => invokeArrayFns(instance.rtg, e) : void 0
}
}
function track(target, type, key) {
if (!dep.has(activeEffect)) {
dep.add(activeEffect)
activeEffect.deps.push(dep)
if ((process.env.NODE_ENV !== 'production') && activeEffect.options.onTrack) {
activeEffect.options.onTrack({
effect: activeEffect,
target,
type,
key
})
}
}
}
function trigger(target, type, key, newValue) {
const run = (effect) => {
if ((process.env.NODE_ENV !== 'production') && effect.options.onTrigger) {
effect.options.onTrigger({
effect,
target,
key,
type,
newValue,
oldValue,
oldTarget
})
}
if (effect.options.scheduler) {
effect.options.scheduler(effect)
} else {
effect()
}
}
effects.forEach(run)
}