MountedVNode,
RenderNode,
createTextVNode,
- Ref,
VNodeChildren
} from './vdom'
import { ComponentInstance } from './component'
const lifecycleHooks: Function[] = []
const vnodeUpdatedHooks: Function[] = []
+ function queuePostCommitHook(fn: Function) {
+ lifecycleHooks.push(fn)
+ }
+
function flushHooks() {
let fn
- while ((fn = lifecycleHooks.shift())) {
+ while ((fn = lifecycleHooks.pop())) {
fn()
}
}
insertOrAppend(container, el, endNode)
}
if (ref) {
- mountRef(ref, el)
+ queuePostCommitHook(() => {
+ ref(el)
+ })
}
if (data != null && data.vnodeMounted) {
- lifecycleHooks.unshift(() => {
+ queuePostCommitHook(() => {
data.vnodeMounted(vnode)
})
}
}
- function mountRef(ref: Ref, el: RenderNode | ComponentInstance) {
- lifecycleHooks.push(() => {
- ref(el)
- })
- }
-
function mountComponent(
vnode: VNode,
container: RenderNode | null,
const { children, childFlags } = vnode
switch (childFlags) {
case ChildrenFlags.SINGLE_VNODE:
+ queuePostCommitHook(() => {
+ vnode.el = (children as MountedVNode).el
+ })
mount(children as VNode, container, contextVNode, isSVG, endNode)
- vnode.el = (children as MountedVNode).el
break
case ChildrenFlags.NO_CHILDREN:
const placeholder = createTextVNode('')
vnode.el = placeholder.el
break
default:
+ queuePostCommitHook(() => {
+ vnode.el = (children as MountedVNode[])[0].el
+ })
mountArrayChildren(
children as VNode[],
container,
isSVG,
endNode
)
- vnode.el = (children as MountedVNode[])[0].el
}
}
)
}
if (ref) {
- mountRef(ref, target as RenderNode)
+ queuePostCommitHook(() => {
+ ref(target)
+ })
}
const placeholder = createTextVNode('')
mountText(placeholder, container, null)
// then retrieve its next sibling to use as the end node for patchChildren.
const endNode = platformNextSibling(getVNodeLastEl(prevVNode))
const { childFlags, children } = nextVNode
+ queuePostCommitHook(() => {
+ switch (childFlags) {
+ case ChildrenFlags.SINGLE_VNODE:
+ nextVNode.el = (children as MountedVNode).el
+ break
+ case ChildrenFlags.NO_CHILDREN:
+ nextVNode.el = prevVNode.el
+ break
+ default:
+ nextVNode.el = (children as MountedVNode[])[0].el
+ }
+ })
patchChildren(
prevVNode.childFlags,
childFlags,
isSVG,
endNode
)
- switch (childFlags) {
- case ChildrenFlags.SINGLE_VNODE:
- nextVNode.el = (children as MountedVNode).el
- break
- case ChildrenFlags.NO_CHILDREN:
- nextVNode.el = prevVNode.el
- break
- default:
- nextVNode.el = (children as MountedVNode[])[0].el
- }
}
function getVNodeLastEl(vnode: MountedVNode): RenderNode {
container: RenderNode | null,
isSVG: boolean,
endNode: RenderNode | null
- ): RenderNode {
+ ) {
if (__DEV__) {
pushWarningContext(vnode)
}
} else {
// this will be executed synchronously right here
instance.$vnode = renderInstanceRoot(instance) as MountedVNode
+
+ queuePostCommitHook(() => {
+ vnode.el = instance.$vnode.el
+ if (vnode.ref) {
+ vnode.ref($proxy)
+ }
+ // retrieve mounted value after initial render so that we get
+ // to inject effects in hooks
+ const { mounted } = instance.$options
+ if (mounted) {
+ callLifecycleHookWithHandle(mounted, $proxy, ErrorTypes.MOUNTED)
+ }
+ })
+
mount(
instance.$vnode,
container,
isSVG,
endNode
)
- vnode.el = instance.$vnode.el
if (__COMPAT__) {
// expose __vue__ for devtools
}
instance._mounted = true
- if (vnode.ref) {
- mountRef(vnode.ref, $proxy)
- }
-
- // retrieve mounted value right before calling it so that we get
- // to inject effects in first render
- const { mounted } = instance.$options
- if (mounted) {
- lifecycleHooks.unshift(() => {
- callLifecycleHookWithHandle(mounted, $proxy, ErrorTypes.MOUNTED)
- })
- }
}
},
{
if (__DEV__) {
popWarningContext()
}
-
- return vnode.el as RenderNode
}
function updateComponentInstance(
const nextVNode = (instance.$vnode = renderInstanceRoot(
instance
) as MountedVNode)
- const container = platformParentNode(prevVNode.el) as RenderNode
- patch(prevVNode, nextVNode, container, $parentVNode as MountedVNode, isSVG)
- const el = nextVNode.el as RenderNode
-
- if (__COMPAT__) {
- // expose __vue__ for devtools
- ;(el as any).__vue__ = instance
- }
- // recursively update contextVNode el for nested HOCs
- if ((nextVNode.flags & VNodeFlags.PORTAL) === 0) {
- let vnode = $parentVNode
- while (vnode !== null) {
- if ((vnode.flags & VNodeFlags.COMPONENT) > 0) {
- vnode.el = el
+ queuePostCommitHook(() => {
+ const el = nextVNode.el as RenderNode
+ if (__COMPAT__) {
+ // expose __vue__ for devtools
+ ;(el as any).__vue__ = instance
+ }
+ // recursively update contextVNode el for nested HOCs
+ if ((nextVNode.flags & VNodeFlags.PORTAL) === 0) {
+ let vnode = $parentVNode
+ while (vnode !== null) {
+ if ((vnode.flags & VNodeFlags.COMPONENT) > 0) {
+ vnode.el = el
+ }
+ vnode = vnode.contextVNode
}
- vnode = vnode.contextVNode
}
- }
-
- const { updated } = instance.$options
- if (updated) {
- // Because the child's update is executed by the scheduler and not
- // synchronously within the parent's update call, the child's updated hook
- // will be added to the queue AFTER the parent's, but they should be
- // invoked BEFORE the parent's. Therefore we add them to the head of the
- // queue instead.
- lifecycleHooks.unshift(() => {
+ const { updated } = instance.$options
+ if (updated) {
callLifecycleHookWithHandle(
updated,
$proxy,
ErrorTypes.UPDATED,
nextVNode
)
- })
- }
+ }
+ if (vnodeUpdatedHooks.length > 0) {
+ const vnodeUpdatedHooksForCurrentInstance = vnodeUpdatedHooks.slice()
+ vnodeUpdatedHooks.length = 0
+ queuePostCommitHook(() => {
+ for (let i = 0; i < vnodeUpdatedHooksForCurrentInstance.length; i++) {
+ vnodeUpdatedHooksForCurrentInstance[i]()
+ }
+ })
+ }
+ })
- if (vnodeUpdatedHooks.length > 0) {
- const vnodeUpdatedHooksForCurrentInstance = vnodeUpdatedHooks.slice()
- vnodeUpdatedHooks.length = 0
- lifecycleHooks.unshift(() => {
- for (let i = 0; i < vnodeUpdatedHooksForCurrentInstance.length; i++) {
- vnodeUpdatedHooksForCurrentInstance[i]()
- }
- })
- }
+ const container = platformParentNode(prevVNode.el) as RenderNode
+ patch(prevVNode, nextVNode, container, $parentVNode as MountedVNode, isSVG)
if (__DEV__ && instance.$parentVNode) {
popWarningContext()
if (__DEV__) {
popWarningContext()
}
- lifecycleHooks.push(() => {
+ queuePostCommitHook(() => {
callActivatedHook(instance, true)
})
}