Jelajahi Sumber

fix keep-alive pruning active instance

Evan You 9 tahun lalu
induk
melakukan
c82546c54b

+ 6 - 8
src/core/components/keep-alive.js

@@ -1,6 +1,5 @@
 /* @flow */
 
-import { callHook } from 'core/instance/lifecycle'
 import { getFirstComponentChild } from 'core/vdom/helpers/index'
 
 type VNodeCache = { [key: string]: ?VNode };
@@ -21,13 +20,15 @@ function matches (pattern: string | RegExp, name: string): boolean {
   return false
 }
 
-function pruneCache (cache: VNodeCache, filter: Function) {
+function pruneCache (cache: VNodeCache, current: VNode, filter: Function) {
   for (const key in cache) {
     const cachedNode: ?VNode = cache[key]
     if (cachedNode) {
       const name: ?string = getComponentName(cachedNode.componentOptions)
       if (name && !filter(name)) {
-        pruneCacheEntry(cachedNode)
+        if (cachedNode !== current) {
+          pruneCacheEntry(cachedNode)
+        }
         cache[key] = null
       }
     }
@@ -36,9 +37,6 @@ function pruneCache (cache: VNodeCache, filter: Function) {
 
 function pruneCacheEntry (vnode: ?VNode) {
   if (vnode) {
-    if (!vnode.componentInstance._inactive) {
-      callHook(vnode.componentInstance, 'deactivated')
-    }
     vnode.componentInstance.$destroy()
   }
 }
@@ -64,10 +62,10 @@ export default {
 
   watch: {
     include (val: string | RegExp) {
-      pruneCache(this.cache, name => matches(val, name))
+      pruneCache(this.cache, this._vnode, name => matches(val, name))
     },
     exclude (val: string | RegExp) {
-      pruneCache(this.cache, name => !matches(val, name))
+      pruneCache(this.cache, this._vnode, name => !matches(val, name))
     }
   },
 

+ 30 - 0
test/unit/features/component/component-keep-alive.spec.js

@@ -347,6 +347,9 @@ describe('Component keep-alive', () => {
       assertHookCalls(one, [1, 1, 1, 1, 0])
       assertHookCalls(two, [1, 1, 1, 0, 0])
       vm.include = 'two'
+    }).then(() => {
+      assertHookCalls(one, [1, 1, 1, 1, 1])
+      assertHookCalls(two, [1, 1, 1, 0, 0])
       vm.view = 'one'
     }).then(() => {
       assertHookCalls(one, [2, 2, 1, 1, 1])
@@ -354,6 +357,33 @@ describe('Component keep-alive', () => {
     }).then(done)
   })
 
+  it('should not prune currently active instance', done => {
+    const vm = new Vue({
+      template: `
+        <div>
+          <keep-alive :include="include">
+            <component :is="view"></component>
+          </keep-alive>
+        </div>
+      `,
+      data: {
+        view: 'one',
+        include: 'one,two'
+      },
+      components
+    }).$mount()
+
+    vm.include = 'two'
+    waitForUpdate(() => {
+      assertHookCalls(one, [1, 1, 1, 0, 0])
+      assertHookCalls(two, [0, 0, 0, 0, 0])
+      vm.view = 'two'
+    }).then(() => {
+      assertHookCalls(one, [1, 1, 1, 0, 1])
+      assertHookCalls(two, [1, 1, 1, 0, 0])
+    }).then(done)
+  })
+
   // #3882
   it('deeply nested keep-alive should be destroyed properly', done => {
     one.template = `<div><keep-alive><two></two></keep-alive></div>`