From 70dc3e3ae74f08d53243e6f078794c16f359e272 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 14 Feb 2020 21:04:08 -0500 Subject: [PATCH] feat(ssr): support portal hydration --- packages/runtime-core/src/hydration.ts | 33 +++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts index bb9b80af7f..2a9e0b1650 100644 --- a/packages/runtime-core/src/hydration.ts +++ b/packages/runtime-core/src/hydration.ts @@ -11,7 +11,13 @@ import { queuePostFlushCb, flushPostFlushCbs } from './scheduler' import { ComponentInternalInstance } from './component' import { invokeDirectiveHook } from './directives' import { warn } from './warning' -import { PatchFlags, ShapeFlags, isReservedProp, isOn } from '@vue/shared' +import { + PatchFlags, + ShapeFlags, + isReservedProp, + isOn, + isString +} from '@vue/shared' import { RendererOptions, MountComponentFn } from './renderer' export type RootHydrateFunction = ( @@ -38,8 +44,6 @@ export function createHydrationFunctions( } // TODO handle mismatches - // TODO SVG - // TODO Suspense const hydrateNode = ( node: Node, vnode: VNode, @@ -62,8 +66,8 @@ export function createHydrationFunctions( // back anchor as expected. return anchor.nextSibling case Portal: - // TODO - break + hydratePortal(vnode, parentComponent) + return node.nextSibling default: if (shapeFlag & ShapeFlags.ELEMENT) { return hydrateElement(node as Element, vnode, parentComponent) @@ -75,7 +79,7 @@ export function createHydrationFunctions( const subTree = vnode.component!.subTree return (subTree.anchor || subTree.el).nextSibling } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) { - // TODO + // TODO Suspense } else if (__DEV__) { warn('Invalid HostVNode type:', type, `(${typeof type})`) } @@ -147,5 +151,22 @@ export function createHydrationFunctions( return node } + const hydratePortal = ( + vnode: VNode, + parentComponent: ComponentInternalInstance | null + ) => { + 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 + ) + } + } + return [hydrate, hydrateNode] as const } -- 2.47.3