diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 6c8ba205e90..c043492e1df 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -345,7 +345,6 @@ function baseCreateRenderer( parentNode: hostParentNode, nextSibling: hostNextSibling, setScopeId: hostSetScopeId = NOOP, - cloneNode: hostCloneNode, insertStaticContent: hostInsertStaticContent } = options @@ -618,82 +617,71 @@ function baseCreateRenderer( ) => { let el: RendererElement let vnodeHook: VNodeHook | undefined | null - const { type, props, shapeFlag, transition, patchFlag, dirs } = vnode - if ( - !__DEV__ && - vnode.el && - hostCloneNode !== undefined && - patchFlag === PatchFlags.HOISTED - ) { - // If a vnode has non-null el, it means it's being reused. - // Only static vnodes can be reused, so its mounted DOM nodes should be - // exactly the same, and we can simply do a clone here. - // only do this in production since cloned trees cannot be HMR updated. - el = vnode.el = hostCloneNode(vnode.el) - } else { - el = vnode.el = hostCreateElement( - vnode.type as string, - isSVG, - props && props.is, - props + const { type, props, shapeFlag, transition, dirs } = vnode + + el = vnode.el = hostCreateElement( + vnode.type as string, + isSVG, + props && props.is, + props + ) + + // mount children first, since some props may rely on child content + // being already rendered, e.g. `` - if (shapeFlag & ShapeFlags.TEXT_CHILDREN) { - hostSetElementText(el, vnode.children as string) - } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) { - mountChildren( - vnode.children as VNodeArrayChildren, - el, - null, - parentComponent, - parentSuspense, - isSVG && type !== 'foreignObject', - slotScopeIds, - optimized - ) + if (dirs) { + invokeDirectiveHook(vnode, null, parentComponent, 'created') + } + // props + if (props) { + for (const key in props) { + if (key !== 'value' && !isReservedProp(key)) { + hostPatchProp( + el, + key, + null, + props[key], + isSVG, + vnode.children as VNode[], + parentComponent, + parentSuspense, + unmountChildren + ) + } } - - if (dirs) { - invokeDirectiveHook(vnode, null, parentComponent, 'created') + /** + * Special case for setting value on DOM elements: + * - it can be order-sensitive (e.g. should be set *after* min/max, #2325, #4024) + * - it needs to be forced (#1471) + * #2353 proposes adding another renderer option to configure this, but + * the properties affects are so finite it is worth special casing it + * here to reduce the complexity. (Special casing it also should not + * affect non-DOM renderers) + */ + if ('value' in props) { + hostPatchProp(el, 'value', null, props.value) } - // props - if (props) { - for (const key in props) { - if (key !== 'value' && !isReservedProp(key)) { - hostPatchProp( - el, - key, - null, - props[key], - isSVG, - vnode.children as VNode[], - parentComponent, - parentSuspense, - unmountChildren - ) - } - } - /** - * Special case for setting value on DOM elements: - * - it can be order-sensitive (e.g. should be set *after* min/max, #2325, #4024) - * - it needs to be forced (#1471) - * #2353 proposes adding another renderer option to configure this, but - * the properties affects are so finite it is worth special casing it - * here to reduce the complexity. (Special casing it also should not - * affect non-DOM renderers) - */ - if ('value' in props) { - hostPatchProp(el, 'value', null, props.value) - } - if ((vnodeHook = props.onVnodeBeforeMount)) { - invokeVNodeHook(vnodeHook, parentComponent, vnode) - } + if ((vnodeHook = props.onVnodeBeforeMount)) { + invokeVNodeHook(vnodeHook, parentComponent, vnode) } - // scopeId - setScopeId(el, vnode, vnode.scopeId, slotScopeIds, parentComponent) } + // scopeId + setScopeId(el, vnode, vnode.scopeId, slotScopeIds, parentComponent) + if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { Object.defineProperty(el, '__vnode', { value: vnode,