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

fix(transition): fix appear check for transition wrapper components (#9668)

DSha 7 лет назад
Родитель
Сommit
4de4649d96

+ 1 - 1
examples/modal/index.html

@@ -10,7 +10,7 @@
   <body>
     <!-- template for the modal component -->
     <script type="text/x-template" id="modal-template">
-      <transition name="modal">
+      <transition name="modal" appear>
         <div class="modal-mask">
           <div class="modal-wrapper">
             <div class="modal-container">

+ 1 - 1
src/platforms/web/runtime/modules/transition.js

@@ -66,8 +66,8 @@ export function enter (vnode: VNodeWithData, toggleDisplay: ?() => void) {
   let context = activeInstance
   let transitionNode = activeInstance.$vnode
   while (transitionNode && transitionNode.parent) {
-    transitionNode = transitionNode.parent
     context = transitionNode.context
+    transitionNode = transitionNode.parent
   }
 
   const isAppear = !context._isMounted || !vnode.isRootInsert

+ 115 - 3
test/unit/features/transition/transition.spec.js

@@ -842,7 +842,7 @@ if (!isIE9) {
       }).then(done)
     })
 
-    it('transition inside child component', done => {
+    it('transition inside child component with v-if', done => {
       const vm = new Vue({
         template: `
           <div>
@@ -872,14 +872,126 @@ if (!isIE9) {
         expect(vm.$el.children.length).toBe(0)
         vm.ok = true
       }).then(() => {
-        expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
+        expect(vm.$el.children[0].className).toBe('test')
+      }).then(done)
+    })
+
+    it('transition with appear inside child component with v-if', done => {
+      const vm = new Vue({
+        template: `
+          <div>
+            <test v-if="ok" class="test"></test>
+          </div>
+        `,
+        data: { ok: true },
+        components: {
+          test: {
+            template: `
+              <transition appear
+                appear-class="test-appear"
+                appear-to-class="test-appear-to"
+                appear-active-class="test-appear-active">
+                <div>foo</div>
+              </transition>
+            `
+          }
+        }
+      }).$mount(el)
+
+      waitForUpdate(() => {
+        expect(vm.$el.children[0].className).toBe('test test-appear test-appear-active')
       }).thenWaitFor(nextFrame).then(() => {
-        expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
+        expect(vm.$el.children[0].className).toBe('test test-appear-active test-appear-to')
+      }).thenWaitFor(duration + buffer).then(() => {
+        expect(vm.$el.children[0].className).toBe('test')
+        vm.ok = false
+      }).then(() => {
+        expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
+      }).thenWaitFor(duration + buffer).then(() => {
+        expect(vm.$el.children.length).toBe(0)
+      }).then(done)
+    })
+
+    it('transition inside nested child component with v-if', done => {
+      const vm = new Vue({
+        template: `
+          <div>
+            <foo v-if="ok" class="test"></foo>
+          </div>
+        `,
+        data: { ok: true },
+        components: {
+          foo: {
+            template: '<bar></bar>',
+            components: {
+              bar: {
+                template: '<transition><div>foo</div></transition>'
+              }
+            }
+          }
+        }
+      }).$mount(el)
+
+      // should not apply transition on initial render by default
+      expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
+      vm.ok = false
+      waitForUpdate(() => {
+        expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
       }).thenWaitFor(duration + buffer).then(() => {
+        expect(vm.$el.children.length).toBe(0)
+        vm.ok = true
+      }).then(() => {
         expect(vm.$el.children[0].className).toBe('test')
       }).then(done)
     })
 
+    it('transition with appear inside nested child component with v-if', done => {
+      const vm = new Vue({
+        template: `
+          <div>
+            <foo v-if="ok" class="test"></foo>
+          </div>
+        `,
+        data: { ok: true },
+        components: {
+          foo: {
+            template: '<bar></bar>',
+            components: {
+              bar: {
+                template: `
+                  <transition appear
+                    appear-class="test-appear"
+                    appear-to-class="test-appear-to"
+                    appear-active-class="test-appear-active">
+                    <div>foo</div>
+                  </transition>
+                `
+              }
+            }
+          }
+        }
+      }).$mount(el)
+
+      waitForUpdate(() => {
+        expect(vm.$el.children[0].className).toBe('test test-appear test-appear-active')
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.children[0].className).toBe('test test-appear-active test-appear-to')
+      }).thenWaitFor(duration + buffer).then(() => {
+        expect(vm.$el.children[0].className).toBe('test')
+        vm.ok = false
+      }).then(() => {
+        expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
+      }).thenWaitFor(duration + buffer).then(() => {
+        expect(vm.$el.children.length).toBe(0)
+      }).then(done)
+    })
+
     it('custom transition higher-order component', done => {
       const vm = new Vue({
         template: '<div><my-transition><div v-if="ok" class="test">foo</div></my-transition></div>',