فهرست منبع

fix(transition): avoid move transition for hidden v-show group children (#14895)

close #14894
edison 2 روز پیش
والد
کامیت
c11f6ee644
2فایلهای تغییر یافته به همراه99 افزوده شده و 1 حذف شده
  1. 7 1
      packages/runtime-dom/src/components/TransitionGroup.ts
  2. 92 0
      packages/vue/__tests__/e2e/TransitionGroup.spec.ts

+ 7 - 1
packages/runtime-dom/src/components/TransitionGroup.ts

@@ -9,6 +9,7 @@ import {
   resolveTransitionProps,
   vtcKey,
 } from './Transition'
+import { type VShowElement, vShowHidden } from '../directives/vShow'
 import {
   type ComponentOptions,
   DeprecationTypes,
@@ -139,7 +140,12 @@ const TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({
       if (children) {
         for (let i = 0; i < children.length; i++) {
           const child = children[i]
-          if (child.el && child.el instanceof Element) {
+          if (
+            child.el &&
+            child.el instanceof Element &&
+            // Hidden v-show nodes have no previous layout box to animate from.
+            !(child.el as VShowElement)[vShowHidden]
+          ) {
             prevChildren.push(child)
             setTransitionHooks(
               child,

+ 92 - 0
packages/vue/__tests__/e2e/TransitionGroup.spec.ts

@@ -297,6 +297,98 @@ describe('e2e: TransitionGroup', () => {
     E2E_TIMEOUT,
   )
 
+  test(
+    'v-show enter does not also run move transition',
+    async () => {
+      await page().evaluate(duration => {
+        const { createApp, ref, onMounted } = (window as any).Vue
+        createApp({
+          template: `
+            <div id="container">
+              <transition-group name="show-group" tag="div" id="showGroup">
+                <div
+                  v-for="item in items"
+                  :key="item"
+                  :id="\`show-\${item}\`"
+                  v-show="visibleItems.includes(item)"
+                  class="show-item"
+                >
+                  {{ item }}
+                </div>
+              </transition-group>
+            </div>
+            <button id="toggleBtn" @click="click">button</button>
+          `,
+          setup: () => {
+            const items = ref(['a', 'b', 'c'])
+            const visibleItems = ref(['a', 'c'])
+            const click = () => (visibleItems.value = ['a', 'b', 'c'])
+
+            onMounted(() => {
+              const styleNode = document.createElement('style')
+              styleNode.textContent = `
+                #showGroup {
+                  display: flex;
+                  gap: 5px;
+                }
+                #showGroup > .show-item {
+                  width: 100px;
+                  height: 20px;
+                }
+                .show-group-enter-active,
+                .show-group-move {
+                  transition: transform ${duration}ms ease;
+                }
+                .show-group-enter-from {
+                  transform: translateX(1000px);
+                }
+              `
+              document.head.appendChild(styleNode)
+            })
+
+            return { click, items, visibleItems }
+          },
+        }).mount('#app')
+      }, duration)
+
+      const duringTransition = await page().evaluate(() => {
+        ;(document.querySelector('#toggleBtn') as any)!.click()
+        return Promise.resolve().then(() =>
+          Array.from(document.querySelectorAll('.show-item')).map(node => ({
+            text: node.textContent!.trim(),
+            classes: Array.from(node.classList),
+            inlineTransform: (node as HTMLElement).style.transform,
+          })),
+        )
+      })
+
+      expect(duringTransition).toStrictEqual([
+        {
+          text: 'a',
+          classes: ['show-item'],
+          inlineTransform: '',
+        },
+        {
+          text: 'b',
+          classes: [
+            'show-item',
+            'show-group-enter-from',
+            'show-group-enter-active',
+          ],
+          inlineTransform: '',
+        },
+        {
+          text: 'c',
+          classes: ['show-item', 'show-group-move'],
+          inlineTransform: '',
+        },
+      ])
+
+      await transitionFinish()
+    },
+    E2E_TIMEOUT,
+  )
+
   test(
     'move while entering',
     async () => {