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

fix keep-alive cache incorrectly pruned with transition mode="out-in" (fix #5346)

Evan You 9 лет назад
Родитель
Сommit
354c2f4922

+ 5 - 3
src/platforms/web/runtime/components/transition.js

@@ -53,9 +53,11 @@ export function extractTransitionData (comp: Component): Object {
 }
 
 function placeholder (h: Function, rawChild: VNode): ?VNode {
-  return /\d-keep-alive$/.test(rawChild.tag)
-    ? h('keep-alive')
-    : null
+  if (/\d-keep-alive$/.test(rawChild.tag)) {
+    return h('keep-alive', {
+      props: rawChild.componentOptions.propsData
+    })
+  }
 }
 
 function hasParentTransition (vnode: VNode): ?boolean {

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

@@ -497,6 +497,91 @@ describe('Component keep-alive', () => {
       }).then(done)
     })
 
+    it('with transition-mode out-in + include', done => {
+      let next
+      const vm = new Vue({
+        template: `<div>
+          <transition name="test" mode="out-in" @after-leave="afterLeave">
+            <keep-alive include="one">
+              <component :is="view" class="test"></component>
+            </keep-alive>
+          </transition>
+        </div>`,
+        data: {
+          view: 'one'
+        },
+        components,
+        methods: {
+          afterLeave () {
+            next()
+          }
+        }
+      }).$mount(el)
+      expect(vm.$el.textContent).toBe('one')
+      assertHookCalls(one, [1, 1, 1, 0, 0])
+      assertHookCalls(two, [0, 0, 0, 0, 0])
+      vm.view = 'two'
+      waitForUpdate(() => {
+        expect(vm.$el.innerHTML).toBe(
+          '<div class="test test-leave test-leave-active">one</div><!---->'
+        )
+        assertHookCalls(one, [1, 1, 1, 1, 0])
+        assertHookCalls(two, [0, 0, 0, 0, 0])
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.innerHTML).toBe(
+          '<div class="test test-leave-active test-leave-to">one</div><!---->'
+        )
+      }).thenWaitFor(_next => { next = _next }).then(() => {
+        expect(vm.$el.innerHTML).toBe('<!---->')
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.innerHTML).toBe(
+          '<div class="test test-enter test-enter-active">two</div>'
+        )
+        assertHookCalls(one, [1, 1, 1, 1, 0])
+        assertHookCalls(two, [1, 1, 0, 0, 0])
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.innerHTML).toBe(
+          '<div class="test test-enter-active test-enter-to">two</div>'
+        )
+      }).thenWaitFor(duration + buffer).then(() => {
+        expect(vm.$el.innerHTML).toBe(
+          '<div class="test">two</div>'
+        )
+        assertHookCalls(one, [1, 1, 1, 1, 0])
+        assertHookCalls(two, [1, 1, 0, 0, 0])
+      }).then(() => {
+        vm.view = 'one'
+      }).then(() => {
+        expect(vm.$el.innerHTML).toBe(
+          '<div class="test test-leave test-leave-active">two</div><!---->'
+        )
+        assertHookCalls(one, [1, 1, 1, 1, 0])
+        assertHookCalls(two, [1, 1, 0, 0, 1])
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.innerHTML).toBe(
+          '<div class="test test-leave-active test-leave-to">two</div><!---->'
+        )
+      }).thenWaitFor(_next => { next = _next }).then(() => {
+        expect(vm.$el.innerHTML).toBe('<!---->')
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.innerHTML).toBe(
+          '<div class="test test-enter test-enter-active">one</div>'
+        )
+        assertHookCalls(one, [1, 1, 2, 1, 0])
+        assertHookCalls(two, [1, 1, 0, 0, 1])
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.innerHTML).toBe(
+          '<div class="test test-enter-active test-enter-to">one</div>'
+        )
+      }).thenWaitFor(duration + buffer).then(() => {
+        expect(vm.$el.innerHTML).toBe(
+          '<div class="test">one</div>'
+        )
+        assertHookCalls(one, [1, 1, 2, 1, 0])
+        assertHookCalls(two, [1, 1, 0, 0, 1])
+      }).then(done)
+    })
+
     it('with transition-mode in-out', done => {
       let next
       const vm = new Vue({