Przeglądaj źródła

transition refactoring

Evan You 10 lat temu
rodzic
commit
93501f2002

+ 1 - 2
src/platforms/web/compiler/modules/transition.js

@@ -11,13 +11,12 @@ function parse (el: ASTElement) {
   }
   if (transition) {
     el.transition = transition
-    el.transitionOnAppear = getBindingAttr(el, 'transition-on-appear') != null
   }
 }
 
 function genData (el: ASTElement): string {
   return el.transition
-    ? `transition:{definition:(${el.transition}),appear:${el.transitionOnAppear}},`
+    ? `transition:${el.transition},`
     : ''
 }
 

+ 38 - 36
src/platforms/web/runtime/modules/transition.js

@@ -47,7 +47,7 @@ export function enter (vnode: VNodeWithData) {
     return
   }
   const isAppear = !vnode.context.$root._isMounted
-  if (isAppear && !data.appear) {
+  if (isAppear && !data.appear && data.appear !== '') {
     return
   }
 
@@ -58,39 +58,44 @@ export function enter (vnode: VNodeWithData) {
     appearClass,
     appearActiveClass,
     beforeEnter,
-    enter,
+    onEnter,
     afterEnter,
-    enterCancelled
-  } = resolveTransition(data.definition, vnode.context)
+    enterCancelled,
+    beforeAppear,
+    onAppear,
+    afterAppear,
+    appearCancelled
+  } = resolveTransition(data, vnode.context)
 
   const startClass = isAppear ? appearClass : enterClass
   const activeClass = isAppear ? appearActiveClass : enterActiveClass
+  const beforeEnterHook = isAppear ? (beforeAppear || beforeEnter) : beforeEnter
+  const enterHook = isAppear ? (onAppear || onEnter) : onEnter
+  const afterEnterHook = isAppear ? (afterAppear || afterEnter) : afterEnter
+  const enterCancelledHook = isAppear ? (appearCancelled || enterCancelled) : enterCancelled
+
   const expectsCSS = css !== false
-  const userWantsControl = enter && enter.length > 1
+  const userWantsControl = enterHook && enterHook.length > 1
   const cb = el._enterCb = once(() => {
-    if (activeClass) {
+    if (expectsCSS) {
       removeTransitionClass(el, activeClass)
     }
     if (cb.cancelled) {
-      if (startClass) {
+      if (expectsCSS) {
         removeTransitionClass(el, startClass)
       }
-      enterCancelled && enterCancelled(el)
+      enterCancelledHook && enterCancelledHook(el)
     } else {
-      afterEnter && afterEnter(el)
+      afterEnterHook && afterEnterHook(el)
     }
     el._enterCb = null
   })
 
-  beforeEnter && beforeEnter(el)
-  if (startClass && expectsCSS) {
+  beforeEnterHook && beforeEnterHook(el)
+  if (expectsCSS) {
     addTransitionClass(el, startClass)
     nextFrame(() => {
       removeTransitionClass(el, startClass)
-    })
-  }
-  if (activeClass && expectsCSS) {
-    nextFrame(() => {
       if (!cb.cancelled) {
         addTransitionClass(el, activeClass)
         if (!userWantsControl) {
@@ -99,8 +104,8 @@ export function enter (vnode: VNodeWithData) {
       }
     })
   }
-  enter && enter(el, cb)
-  if ((!expectsCSS || !activeClass) && !userWantsControl) {
+  enterHook && enterHook(el, cb)
+  if (!expectsCSS && !userWantsControl) {
     cb()
   }
 }
@@ -122,19 +127,19 @@ export function leave (vnode: VNodeWithData, rm: Function) {
     leaveClass,
     leaveActiveClass,
     beforeLeave,
-    leave,
+    onLeave,
     afterLeave,
     leaveCancelled
-  } = resolveTransition(data.definition, vnode.context)
+  } = resolveTransition(data, vnode.context)
 
   const expectsCSS = css !== false
-  const userWantsControl = leave && leave.length > 1
+  const userWantsControl = onLeave && onLeave.length > 1
   const cb = el._leaveCb = once(() => {
-    if (leaveActiveClass) {
+    if (expectsCSS) {
       removeTransitionClass(el, leaveActiveClass)
     }
     if (cb.cancelled) {
-      if (leaveClass) {
+      if (expectsCSS) {
         removeTransitionClass(el, leaveClass)
       }
       leaveCancelled && leaveCancelled(el)
@@ -146,14 +151,10 @@ export function leave (vnode: VNodeWithData, rm: Function) {
   })
 
   beforeLeave && beforeLeave(el)
-  if (leaveClass && expectsCSS) {
+  if (expectsCSS) {
     addTransitionClass(el, leaveClass)
     nextFrame(() => {
       removeTransitionClass(el, leaveClass)
-    })
-  }
-  if (leaveActiveClass && expectsCSS) {
-    nextFrame(() => {
       if (!cb.cancelled) {
         addTransitionClass(el, leaveActiveClass)
         if (!userWantsControl) {
@@ -162,8 +163,8 @@ export function leave (vnode: VNodeWithData, rm: Function) {
       }
     })
   }
-  leave && leave(el, cb)
-  if ((!expectsCSS || !leaveActiveClass) && !userWantsControl) {
+  onLeave && onLeave(el, cb)
+  if (!expectsCSS && !userWantsControl) {
     cb()
   }
 }
@@ -172,23 +173,24 @@ function resolveTransition (id: string | Object, context: Component): Object {
   if (id && typeof id === 'string') {
     const def = resolveAsset(context.$options, 'transitions', id)
     if (def) {
-      return ensureTransitionClasses(id, def)
+      return ensureTransitionClasses(def.name || id, def)
     } else {
       return autoCssTransition(id)
     }
   } else if (typeof id === 'object') { // inline transition object
-    return ensureTransitionClasses('v', id)
+    return ensureTransitionClasses(id.name, id)
   } else {
     return autoCssTransition('v')
   }
 }
 
-function ensureTransitionClasses (id: string, def: Object): Object {
+function ensureTransitionClasses (name: ?string, def: Object): Object {
   if (def.css === false) return def
-  const key = `_cache_${id}`
+  name = name || 'v'
+  const key = `_cache_${name}`
   if (def[key]) return def[key]
   const res = def[key] = {}
-  extend(res, autoCssTransition(id))
+  extend(res, autoCssTransition(name))
   extend(res, def)
   return res
 }
@@ -197,10 +199,10 @@ const autoCssTransition: (name: string) => Object = cached(name => {
   return {
     enterClass: `${name}-enter`,
     leaveClass: `${name}-leave`,
-    appearClass: `${name}-appear`,
+    appearClass: `${name}-enter`,
     enterActiveClass: `${name}-enter-active`,
     leaveActiveClass: `${name}-leave-active`,
-    appearActiveClass: `${name}-appear-active`
+    appearActiveClass: `${name}-enter-active`
   }
 })
 

+ 33 - 16
test/unit/features/transition/transition.spec.js

@@ -10,8 +10,8 @@ if (!isIE9) {
         -webkit-transition: opacity ${duration}ms ease;
         transition: opacity ${duration}ms ease;
       }
-      .v-enter, .v-leave-active,
-      .test-enter, .test-leave-active,
+      .v-appear, .v-enter, .v-leave-active,
+      .test-appear, .test-enter, .test-leave-active,
       .hello, .bye.active,
       .changed-enter {
         opacity: 0;
@@ -199,14 +199,14 @@ if (!isIE9) {
           expect(el.className).toBe('test')
           beforeLeaveSpy()
         },
-        leave: jasmine.createSpy('leave'),
+        onLeave: jasmine.createSpy('leave'),
         afterLeave: jasmine.createSpy('afterLeave'),
         beforeEnter: el => {
           expect(vm.$el.contains(el)).toBe(false)
           expect(el.className).toBe('test')
           beforeEnterSpy()
         },
-        enter: jasmine.createSpy('enter'),
+        onEnter: jasmine.createSpy('enter'),
         afterEnter: jasmine.createSpy('afterEnter')
       }
 
@@ -223,7 +223,7 @@ if (!isIE9) {
       vm.ok = false
       waitForUpdate(() => {
         expect(beforeLeaveSpy).toHaveBeenCalled()
-        expect(hooks.leave).toHaveBeenCalled()
+        expect(hooks.onLeave).toHaveBeenCalled()
         expect(vm.$el.children[0].className).toBe('test test-leave')
       }).thenWaitFor(nextFrame).then(() => {
         expect(hooks.afterLeave).not.toHaveBeenCalled()
@@ -234,7 +234,7 @@ if (!isIE9) {
         vm.ok = true
       }).then(() => {
         expect(beforeEnterSpy).toHaveBeenCalled()
-        expect(hooks.enter).toHaveBeenCalled()
+        expect(hooks.onEnter).toHaveBeenCalled()
         expect(vm.$el.children[0].className).toBe('test test-enter')
       }).thenWaitFor(nextFrame).then(() => {
         expect(hooks.afterEnter).not.toHaveBeenCalled()
@@ -252,10 +252,10 @@ if (!isIE9) {
         data: { ok: true },
         transitions: {
           test: {
-            enter: (el, cb) => {
+            onEnter: (el, cb) => {
               next = cb
             },
-            leave: (el, cb) => {
+            onLeave: (el, cb) => {
               next = cb
             }
           }
@@ -294,8 +294,8 @@ if (!isIE9) {
         transitions: {
           test: {
             css: false,
-            enter: enterSpy,
-            leave: leaveSpy
+            onEnter: enterSpy,
+            onLeave: leaveSpy
           }
         }
       }).$mount(el)
@@ -319,8 +319,8 @@ if (!isIE9) {
         data: { ok: true },
         transitions: {
           nope: {
-            enter: enterSpy,
-            leave: leaveSpy
+            onEnter: enterSpy,
+            onLeave: leaveSpy
           }
         }
       }).$mount(el)
@@ -452,7 +452,18 @@ if (!isIE9) {
 
     it('transition on appear', done => {
       const vm = new Vue({
-        template: '<div><div v-if="ok" class="test" transition="test" transition-on-appear>foo</div></div>',
+        template: `
+          <div>
+            <div v-if="ok"
+              class="test"
+              :transition="{
+                name:'test',
+                appear:true,
+                appearClass: 'test-appear',
+                appearActiveClass: 'test-appear-active'
+              }">foo</div>
+          </div>
+        `,
         data: { ok: true }
       }).$mount(el)
 
@@ -467,14 +478,20 @@ if (!isIE9) {
 
     it('transition on appear with v-show', done => {
       const vm = new Vue({
-        template: '<div><div v-show="ok" class="test" transition="test" transition-on-appear>foo</div></div>',
+        template: `
+          <div>
+            <div v-show="ok"
+              class="test"
+              :transition="{name:'test',appear:true}">foo</div>
+          </div>
+        `,
         data: { ok: true }
       }).$mount(el)
 
       waitForUpdate(() => {
-        expect(vm.$el.children[0].className).toBe('test test-appear')
+        expect(vm.$el.children[0].className).toBe('test test-enter')
       }).thenWaitFor(nextFrame).then(() => {
-        expect(vm.$el.children[0].className).toBe('test test-appear-active')
+        expect(vm.$el.children[0].className).toBe('test test-enter-active')
       }).thenWaitFor(timeout(duration + 10)).then(() => {
         expect(vm.$el.children[0].className).toBe('test')
       }).then(done)

+ 3 - 3
test/unit/modules/compiler/codegen.spec.js

@@ -179,14 +179,14 @@ describe('codegen', () => {
   it('generate transition', () => {
     assertCodegen(
       '<p transition="expand">hello world</p>',
-      `with(this){return _h(_e('p',{transition:{definition:("expand"),appear:false}}),[_t("hello world")])}`
+      `with(this){return _h(_e('p',{transition:"expand"}),[_t("hello world")])}`
     )
   })
 
   it('generate dynamic transition with transition on appear', () => {
     assertCodegen(
-      '<p :transition="expand" transition-on-appear>hello world</p>',
-      `with(this){return _h(_e('p',{transition:{definition:(expand),appear:true}}),[_t("hello world")])}`
+      `<p :transition="{name:'expand',appear:true}">hello world</p>`,
+      `with(this){return _h(_e('p',{transition:{name:'expand',appear:true}}),[_t("hello world")])}`
     )
   })
 

+ 0 - 2
test/unit/modules/compiler/parser.spec.js

@@ -227,13 +227,11 @@ describe('parser', () => {
   it('transition', () => {
     const ast = parse('<p v-if="show" transition="expand">hello world</p>', baseOptions)
     expect(ast.transition).toBe('"expand"')
-    expect(ast.transitionOnAppear).toBe(false)
   })
 
   it('transition with empty', () => {
     const ast = parse('<p v-if="show" transition="">hello world</p>', baseOptions)
     expect(ast.transition).toBe(true)
-    expect(ast.transitionOnAppear).toBe(false)
   })
 
   it('attribute with v-bind', () => {