]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(keep-alive): should update re-activated component with latest props
authorEvan You <yyx990803@gmail.com>
Tue, 24 Mar 2020 14:28:00 +0000 (10:28 -0400)
committerEvan You <yyx990803@gmail.com>
Tue, 24 Mar 2020 14:28:00 +0000 (10:28 -0400)
packages/runtime-core/__tests__/components/KeepAlive.spec.ts
packages/runtime-core/src/components/KeepAlive.ts
packages/runtime-core/src/renderer.ts

index 9bcec22e58667ed92ccd05b9f8ae7d06b124bdb2..be17b0772f64fb45a0c6bf65e98d0acda023f038 100644 (file)
@@ -531,5 +531,32 @@ describe('KeepAlive', () => {
       await nextTick()
       expect(Foo.unmounted).not.toHaveBeenCalled()
     })
+
+    test('should update re-activated component if props have changed', async () => {
+      const Foo = (props: { n: number }) => props.n
+
+      const toggle = ref(true)
+      const n = ref(0)
+
+      const App = {
+        setup() {
+          return () =>
+            h(KeepAlive, () => (toggle.value ? h(Foo, { n: n.value }) : null))
+        }
+      }
+
+      render(h(App), root)
+      expect(serializeInner(root)).toBe(`0`)
+
+      toggle.value = false
+      await nextTick()
+      expect(serializeInner(root)).toBe(`<!---->`)
+
+      n.value++
+      await nextTick()
+      toggle.value = true
+      await nextTick()
+      expect(serializeInner(root)).toBe(`1`)
+    })
   })
 })
index c66fd50dae8d4ce35de6df28be36b63b90db97cb..c2506309340934394491be14583bf517606a026f 100644 (file)
@@ -41,7 +41,9 @@ export interface KeepAliveSink {
   activate: (
     vnode: VNode,
     container: RendererElement,
-    anchor: RendererNode | null
+    anchor: RendererNode | null,
+    isSVG: boolean,
+    optimized: boolean
   ) => void
   deactivate: (vnode: VNode) => void
 }
@@ -78,6 +80,7 @@ const KeepAliveImpl = {
     const sink = instance.sink as KeepAliveSink
     const {
       renderer: {
+        p: patch,
         m: move,
         um: _unmount,
         o: { createElement }
@@ -86,13 +89,24 @@ const KeepAliveImpl = {
     } = sink
     const storageContainer = createElement('div')
 
-    sink.activate = (vnode, container, anchor) => {
+    sink.activate = (vnode, container, anchor, isSVG, optimized) => {
+      const child = vnode.component!
       move(vnode, container, anchor, MoveType.ENTER, parentSuspense)
+      // in case props have changed
+      patch(
+        child.vnode,
+        vnode,
+        container,
+        anchor,
+        instance,
+        parentSuspense,
+        isSVG,
+        optimized
+      )
       queuePostRenderEffect(() => {
-        const component = vnode.component!
-        component.isDeactivated = false
-        if (component.a) {
-          invokeHooks(component.a)
+        child.isDeactivated = false
+        if (child.a) {
+          invokeHooks(child.a)
         }
       }, parentSuspense)
     }
@@ -181,7 +195,7 @@ const KeepAliveImpl = {
       }
 
       const key = vnode.key == null ? comp : vnode.key
-      const cached = cache.get(key)
+      const cachedVNode = cache.get(key)
 
       // clone vnode if it's reused because we are going to mutate it
       if (vnode.el) {
@@ -189,11 +203,11 @@ const KeepAliveImpl = {
       }
       cache.set(key, vnode)
 
-      if (cached) {
+      if (cachedVNode) {
         // copy over mounted state
-        vnode.el = cached.el
-        vnode.anchor = cached.anchor
-        vnode.component = cached.component
+        vnode.el = cachedVNode.el
+        vnode.anchor = cachedVNode.anchor
+        vnode.component = cachedVNode.component
         if (vnode.transition) {
           // recursively update transition hooks on subTree
           setTransitionHooks(vnode, vnode.transition!)
index 0385a6dcc38f202b19b74ebd323933c0e70bccd0..e80a4976c13873f63088b6268f2ca44f7f9de9c0 100644 (file)
@@ -946,7 +946,9 @@ function baseCreateRenderer(
         ;(parentComponent!.sink as KeepAliveSink).activate(
           n2,
           container,
-          anchor
+          anchor,
+          isSVG,
+          optimized
         )
       } else {
         mountComponent(