Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TransitionGroup: children with same key but rendered in different v-for are not treated as same child #1126

Closed
jonaskuske opened this issue May 5, 2020 · 2 comments
Labels
🐞 bug Something isn't working scope: transition

Comments

@jonaskuske
Copy link
Contributor

jonaskuske commented May 5, 2020

Version

3.0.0-beta.9

Reproduction link

https://codepen.io/21stCenturyJonas/pen/rNOprRG

Steps to reproduce

<TransitionGroup>
  <div v-for="item in items.filter(i => i.done === true)" :key="item.id">
    <button @click="item.done = !item.done">Toggle</button>
  </div>
  <div v-for="item in items.filter(i => i.done === false)" :key="item.id">
    <button @click="item.done = !item.done">Toggle</button>
  </div>
</TransitionGroup>

In the example above (with items: [{ id: 1, done: false }, ...]), toggling item.done would trigger a v-move transition in Vue 2, as it'd see the item as being the same and just having changed its position, despite moving from one v-for to the other. Vue 3 treats the item that's removed from the one v-for and the one that now is a part of the other v-for as separate despite the equal key and triggers v-leave and v-enter transitions respectively.

This breaks the transitions in this ToDo app for example, which works in Vue 2 (https://codepen.io/21stCenturyJonas/pen/QWjpxwG) but doesn't in Vue 3: https://codepen.io/21stCenturyJonas/pen/rNOprRG

What is expected?

Due to the same key, the item is moved instead of being removed only to reappear in its new position.

What is actually happening?

The item is removed from its old position and reappears in its new position.


I guess this happens because they actually aren't direct children of <TransitionGroup> anymore but instead there's a <Fragment> in between?

@underfin
Copy link
Member

underfin commented May 6, 2020

You can try merge two v-for into one , like the blow code , hope this help you.

<article
        v-for="todo in todos"
        :key="todo.id"
        :class="[todo.done ? 'column-right' : 'column-left']"
        class="todo column-left"
        @click="todo.done = !todo.done"
    >
// xxx
</article>

Other.I try fix the problem with vue code with packages/runtime-dom/src/components/TransitionGroup.ts#130

      if(slotChildren.filter(n => n.type === Fragment).length > 1){
        children.forEach(n => n.patchFlag = PatchFlags.FULL_PROPS)
      }
      return createVNode(tag, null, children)

It is worked,but it maybe caused hydration error(remove fragment) and add cost of performance with normal code bacause give up the optimized.

@yyx990803 yyx990803 added 🐞 bug Something isn't working scope: transition labels May 6, 2020
@jonaskuske
Copy link
Contributor Author

jonaskuske commented May 8, 2020

You can try merge two v-for into one , like the blow code , hope this help you.

Yep, merging them all into one v-for kinda works, thanks! But the limitation that TransitionGroup only works for child nodes on the same flat level is already quite severe as is (different discussion) – and not being able to freely move keyed items there compounds this unfortunately, because that makes it even harder to maintain tab order and a semantic structure...

@github-actions github-actions bot locked and limited conversation to collaborators Nov 10, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
🐞 bug Something isn't working scope: transition
Projects
None yet
Development

No branches or pull requests

3 participants