]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(transition): handle transition classes when patching classes
authorEvan You <yyx990803@gmail.com>
Fri, 22 Nov 2019 20:31:55 +0000 (15:31 -0500)
committerEvan You <yyx990803@gmail.com>
Fri, 22 Nov 2019 20:35:41 +0000 (15:35 -0500)
packages/runtime-dom/src/components/CSSTransition.ts
packages/runtime-dom/src/modules/class.ts

index ae4107b58453a1fe0175cb432455a4148b46e111..e7a24e8807cdb8d0c2e86c40315f04c465eb0ef3 100644 (file)
@@ -64,19 +64,19 @@ function resolveCSSTransitionData({
     ...baseProps,
     onBeforeEnter(el) {
       onBeforeEnter && onBeforeEnter(el)
-      el.classList.add(enterActiveClass)
-      el.classList.add(enterFromClass)
+      addTransitionClass(el, enterActiveClass)
+      addTransitionClass(el, enterFromClass)
     },
     onEnter(el, done) {
       nextFrame(() => {
         const resolve = () => {
-          el.classList.remove(enterToClass)
-          el.classList.remove(enterActiveClass)
+          removeTransitionClass(el, enterToClass)
+          removeTransitionClass(el, enterActiveClass)
           done()
         }
         onEnter && onEnter(el, resolve)
-        el.classList.remove(enterFromClass)
-        el.classList.add(enterToClass)
+        removeTransitionClass(el, enterFromClass)
+        addTransitionClass(el, enterToClass)
         if (!(onEnter && onEnter.length > 1)) {
           if (enterDuration) {
             setTimeout(resolve, enterDuration)
@@ -87,17 +87,17 @@ function resolveCSSTransitionData({
       })
     },
     onLeave(el, done) {
-      el.classList.add(leaveActiveClass)
-      el.classList.add(leaveFromClass)
+      addTransitionClass(el, leaveActiveClass)
+      addTransitionClass(el, leaveFromClass)
       nextFrame(() => {
         const resolve = () => {
-          el.classList.remove(leaveToClass)
-          el.classList.remove(leaveActiveClass)
+          removeTransitionClass(el, leaveToClass)
+          removeTransitionClass(el, leaveActiveClass)
           done()
         }
         onLeave && onLeave(el, resolve)
-        el.classList.remove(leaveFromClass)
-        el.classList.add(leaveToClass)
+        removeTransitionClass(el, leaveFromClass)
+        addTransitionClass(el, leaveToClass)
         if (!(onLeave && onLeave.length > 1)) {
           if (leaveDuration) {
             setTimeout(resolve, leaveDuration)
@@ -143,6 +143,27 @@ function validateDuration(val: unknown) {
   }
 }
 
+export interface ElementWithTransition extends Element {
+  // _vtc = Vue Transition Classes.
+  // Store the temporarily-added transition classes on the element
+  // so that we can avoid overwriting them if the element's class is patched
+  // during the transition.
+  _vtc?: Set<string>
+}
+
+function addTransitionClass(el: ElementWithTransition, cls: string) {
+  el.classList.add(cls)
+  ;(el._vtc || (el._vtc = new Set())).add(cls)
+}
+
+function removeTransitionClass(el: ElementWithTransition, cls: string) {
+  el.classList.remove(cls)
+  el._vtc!.delete(cls)
+  if (!el._vtc!.size) {
+    el._vtc = undefined
+  }
+}
+
 function nextFrame(cb: () => void) {
   requestAnimationFrame(() => {
     requestAnimationFrame(cb)
index fb9349f2e7590d94a11490f58a70f4c244738dad..9641a952bdeb89c43186d18a7629845c115add8a 100644 (file)
@@ -1,7 +1,17 @@
+import { ElementWithTransition } from '../components/CSSTransition'
+
 // compiler should normalize class + :class bindings on the same element
 // into a single binding ['staticClass', dynamic]
-
-export function patchClass(el: Element, value: string, isSVG: boolean) {
+export function patchClass(
+  el: ElementWithTransition,
+  value: string,
+  isSVG: boolean
+) {
+  // if this is an element during a transition, take the temporary transition
+  // classes into account.
+  if (el._vtc) {
+    value = [value, ...el._vtc].join(' ')
+  }
   // directly setting className should be faster than setAttribute in theory
   if (isSVG) {
     el.setAttribute('class', value)