refactor(hydration): move fragment to seaprate function + skip normalization in optimized mode

This commit is contained in:
Evan You 2020-02-27 11:26:39 -05:00
parent 3357ff438c
commit 4809325c07

View File

@ -39,7 +39,8 @@ export function createHydrationFunctions({
const hydrateNode = (
node: Node,
vnode: VNode,
parentComponent: ComponentInternalInstance | null = null
parentComponent: ComponentInternalInstance | null = null,
optimized = false
): Node | null => {
const { type, shapeFlag } = vnode
vnode.el = node
@ -49,18 +50,15 @@ export function createHydrationFunctions({
case Static:
return node.nextSibling
case Fragment:
const parent = node.parentNode!
parent.insertBefore((vnode.el = createText('')), node)
const next = hydrateChildren(
node,
vnode.children as VNode[],
parentComponent
)
parent.insertBefore((vnode.anchor = createText('')), next)
return next
return hydrateFragment(node, vnode, parentComponent, optimized)
default:
if (shapeFlag & ShapeFlags.ELEMENT) {
return hydrateElement(node as Element, vnode, parentComponent)
return hydrateElement(
node as Element,
vnode,
parentComponent,
optimized
)
} else if (shapeFlag & ShapeFlags.COMPONENT) {
// when setting up the render effect, if the initial vnode already
// has .el set, the component will perform hydration instead of mount
@ -69,7 +67,7 @@ export function createHydrationFunctions({
const subTree = vnode.component!.subTree
return (subTree.anchor || subTree.el).nextSibling
} else if (shapeFlag & ShapeFlags.PORTAL) {
hydratePortal(vnode, parentComponent)
hydratePortal(vnode, parentComponent, optimized)
return node.nextSibling
} else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
// TODO Suspense
@ -83,7 +81,8 @@ export function createHydrationFunctions({
const hydrateElement = (
el: Element,
vnode: VNode,
parentComponent: ComponentInternalInstance | null
parentComponent: ComponentInternalInstance | null,
optimized: boolean
) => {
const { props, patchFlag } = vnode
// skip props & children if this is hoisted static nodes
@ -123,8 +122,9 @@ export function createHydrationFunctions({
) {
hydrateChildren(
el.firstChild,
vnode.children as VNode[],
parentComponent
vnode,
parentComponent,
optimized || vnode.dynamicChildren !== null
)
}
}
@ -133,32 +133,45 @@ export function createHydrationFunctions({
const hydrateChildren = (
node: Node | null,
vnodes: VNode[],
parentComponent: ComponentInternalInstance | null
vnode: VNode,
parentComponent: ComponentInternalInstance | null,
optimized: boolean
): Node | null => {
for (let i = 0; node != null && i < vnodes.length; i++) {
// TODO can skip normalizeVNode in optimized mode
// (need hint on rendered markup?)
const vnode = (vnodes[i] = normalizeVNode(vnodes[i]))
node = hydrateNode(node, vnode, parentComponent)
const children = vnode.children as VNode[]
optimized = optimized || vnode.dynamicChildren !== null
for (let i = 0; node != null && i < children.length; i++) {
const vnode = optimized
? children[i]
: (children[i] = normalizeVNode(children[i]))
node = hydrateNode(node, vnode, parentComponent, optimized)
}
return node
}
const hydrateFragment = (
node: Node,
vnode: VNode,
parentComponent: ComponentInternalInstance | null,
optimized: boolean
) => {
const parent = node.parentNode!
parent.insertBefore((vnode.el = createText('')), node)
const next = hydrateChildren(node, vnode, parentComponent, optimized)
parent.insertBefore((vnode.anchor = createText('')), next)
return next
}
const hydratePortal = (
vnode: VNode,
parentComponent: ComponentInternalInstance | null
parentComponent: ComponentInternalInstance | null,
optimized: boolean
) => {
const targetSelector = vnode.props && vnode.props.target
const target = (vnode.target = isString(targetSelector)
? document.querySelector(targetSelector)
: targetSelector)
if (target != null && vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
hydrateChildren(
target.firstChild,
vnode.children as VNode[],
parentComponent
)
hydrateChildren(target.firstChild, vnode, parentComponent, optimized)
}
}