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

fix(transition-group): avoid invalid hooks on unkeyed interop children

daiwei 1 месяц назад
Родитель
Сommit
82c1223064

+ 14 - 0
packages-private/vapor-e2e-test/__tests__/transition-group.spec.ts

@@ -746,6 +746,20 @@ describe('vapor transition-group', () => {
   )
 
   describe('interop', () => {
+    test('unkeyed vdom component update', async () => {
+      const btnSelector = '.unkeyed-vdom-component-update > button'
+      const containerSelector = '.unkeyed-vdom-component-update > div'
+
+      expect(await html(containerSelector)).toBe(`<div><div>a</div></div>`)
+
+      await page().click(btnSelector)
+
+      await waitForInnerHTML(
+        containerSelector,
+        `<div><div>a</div></div><div class="test">b</div>`,
+      )
+    })
+
     test('static keyed vdom component enter', async () => {
       const btnSelector = '.static-keyed-vdom-component-enter > button'
       const containerSelector = '.static-keyed-vdom-component-enter > div'

+ 21 - 0
packages-private/vapor-e2e-test/transition-group/cases/interop/unkeyed-vdom-component-update.vue

@@ -0,0 +1,21 @@
+<script setup vapor>
+import { ref } from 'vue'
+import VdomComp from '../../components/VdomComp.vue'
+
+const show = ref(false)
+const update = () => (show.value = true)
+</script>
+
+<template>
+  <div class="unkeyed-vdom-component-update">
+    <button @click="update">update button</button>
+    <div>
+      <transition-group name="test">
+        <VdomComp>
+          <div>a</div>
+        </VdomComp>
+        <div v-if="show" key="b" class="test">b</div>
+      </transition-group>
+    </div>
+  </div>
+</template>

+ 9 - 3
packages/runtime-vapor/src/components/TransitionGroup.ts

@@ -41,6 +41,7 @@ import {
   type DefineVaporComponent,
   defineVaporComponent,
 } from '../apiDefineComponent'
+import { isInteropEnabled } from '../vdomInteropState'
 
 const positionMap = new WeakMap<TransitionBlock, DOMRect>()
 const newPositionMap = new WeakMap<TransitionBlock, DOMRect>()
@@ -88,7 +89,7 @@ const VaporTransitionGroupImpl = defineVaporComponent({
       const children = getTransitionBlocks(slottedBlock)
       for (let i = 0; i < children.length; i++) {
         const child = children[i]
-        if (isValidTransitionBlock(child)) {
+        if (isValidTransitionBlock(child) && child.$transition) {
           prevChildren.push(child)
           // disabled transition during enter, so the children will be
           // inserted into the correct position immediately. this prevents
@@ -199,8 +200,13 @@ function applyGroupTransitionHooks(
           child,
           resolveTransitionHooks(child, props, state, instance),
         )
-      } else if (__DEV__) {
-        warn(`<transition-group> children must be keyed`)
+      } else {
+        if (isInteropEnabled && isFragment(child) && child.vnode) {
+          child.$transition = undefined
+        }
+        if (__DEV__) {
+          warn(`<transition-group> children must be keyed`)
+        }
       }
     }
   }