Browse Source

feat: proper static tree skip

Evan You 7 years ago
parent
commit
fc5aa6d0be
2 changed files with 19 additions and 3 deletions
  1. 12 1
      packages/runtime-core/src/createRenderer.ts
  2. 7 2
      packages/runtime-core/src/vdom.ts

+ 12 - 1
packages/runtime-core/src/createRenderer.ts

@@ -477,7 +477,18 @@ export function createRenderer(options: RendererOptions) {
     contextVNode: MountedVNode | null,
     isSVG: boolean
   ) {
-    const { flags, tag } = nextVNode
+    const { flags, tag, clonedFrom } = nextVNode
+
+    // cloned vnodes pointing to the same original.
+    // these are hoisted static trees so just skip entirely
+    if (
+      clonedFrom !== null &&
+      (clonedFrom === prevVNode || clonedFrom === prevVNode.clonedFrom)
+    ) {
+      nextVNode.el = prevVNode.el
+      return
+    }
+
     isSVG = isSVG || (flags & VNodeFlags.ELEMENT_SVG) > 0
 
     if (prevVNode.tag !== tag) {

+ 7 - 2
packages/runtime-core/src/vdom.ts

@@ -43,6 +43,8 @@ export interface VNode {
   // a consistent handle so that a functional component can be identified
   // by the scheduler
   handle: FunctionalHandle | null
+  // only on cloned vnodes, points to the original cloned vnode
+  clonedFrom: VNode | null
 }
 
 export interface MountedVNode extends VNode {
@@ -99,7 +101,8 @@ export function createVNode(
     el: null,
     parentVNode: null,
     contextVNode: null,
-    handle: null
+    handle: null,
+    clonedFrom: null
   }
   if (childFlags === ChildrenFlags.UNKNOWN_CHILDREN) {
     normalizeChildren(vnode, children)
@@ -339,7 +342,7 @@ export function cloneVNode(vnode: VNode, extraData?: VNodeData): VNode {
         }
       }
     }
-    return createVNode(
+    const cloned = createVNode(
       flags,
       vnode.tag,
       clonedData,
@@ -349,6 +352,8 @@ export function cloneVNode(vnode: VNode, extraData?: VNodeData): VNode {
       vnode.ref,
       vnode.slots
     )
+    cloned.clonedFrom = vnode.clonedFrom || vnode
+    return cloned
   } else if (flags & VNodeFlags.TEXT) {
     return createTextVNode(vnode.children as string)
   } else {