Просмотр исходного кода

fix(runtime-core): fix stale v-memo after v-if toggle (#6606)

close #6593
edison 1 год назад
Родитель
Сommit
edf263847e

+ 11 - 0
packages/runtime-core/__tests__/helpers/withMemo.spec.ts

@@ -148,6 +148,17 @@ describe('v-memo', () => {
     // should update
     await nextTick()
     expect(el.innerHTML).toBe(`<div>3 3</div>`)
+
+    vm.ok = true
+    await nextTick()
+    vm.ok = false
+    await nextTick()
+    expect(el.innerHTML).toBe(`<div>3 3</div>`)
+
+    vm.y++
+    // should update
+    await nextTick()
+    expect(el.innerHTML).toBe(`<div>4 3</div>`)
   })
 
   test('on v-for', async () => {

+ 1 - 1
packages/runtime-core/src/component.ts

@@ -322,7 +322,7 @@ export interface ComponentInternalInstance {
    * after initialized (e.g. inline handlers)
    * @internal
    */
-  renderCache: (Function | VNode)[]
+  renderCache: (Function | VNode | undefined)[]
 
   /**
    * Resolved component registry, only for components with mixins or extends

+ 2 - 0
packages/runtime-core/src/helpers/withMemo.ts

@@ -15,6 +15,8 @@ export function withMemo(
 
   // shallow clone
   ret.memo = memo.slice()
+  ret.memoIndex = index
+
   return (cache[index] = ret)
 }
 

+ 6 - 0
packages/runtime-core/src/renderer.ts

@@ -2110,12 +2110,18 @@ function baseCreateRenderer(
       shapeFlag,
       patchFlag,
       dirs,
+      memoIndex,
     } = vnode
     // unset ref
     if (ref != null) {
       setRef(ref, null, parentSuspense, vnode, true)
     }
 
+    // #6593 should clean memo cache when unmount
+    if (memoIndex != null) {
+      parentComponent!.renderCache[memoIndex] = undefined
+    }
+
     if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
       ;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode)
       return

+ 4 - 0
packages/runtime-core/src/vnode.ts

@@ -228,6 +228,10 @@ export interface VNode<
    * @internal attached by v-memo
    */
   memo?: any[]
+  /**
+   * @internal index for cleaning v-memo cache
+   */
+  memoIndex?: number
   /**
    * @internal __COMPAT__ only
    */