0

I can wrap a v-for loop in a transition-group and make all elements appear at the same time like so:

<script setup>
import {onMounted, reactive} from "vue";

const state = reactive({
    hover: false,
    fadeIn: false,
})

onMounted(() => {

    setTimeout(() => {
        state.fadeIn = true
    }, 2000)

})

</script>


<template>
      <transition-group name="fade-1">
        <div class="partner-wrap" v-for="(partner, key) in [1,2,3,4,5]" :key="key" v-if="state.fadeIn">
          <p>I am fading in!</p>
          </div>
      </transition-group>
</template>

But how do I make them appear one by one? I've tried this:

<script setup>
import {onMounted, reactive} from "vue";

const state = reactive({
    hover: false,
    fadeInArray: [false, false, false, false, false]
})

onMounted(() => {

    let val = 0;
    setInterval(() => {
        state.fadeInArray[val] = true
        val++
        if (val == state.fadeInArray.length) {
            clearInterval()
        }
    }, 2000)

})

</script>


<template>
      <transition-group name="fade-1">
        <div class="partner-wrap" v-for="(partner, key) in [1,2,3,4,5]" :key="key">
          <p v-if="state.fadeInArray[key]">I am fading in!</p>
          </div>
      </transition-group>
</template>

but the transition doesn't work and the elements pop in without transition.

Here's my transition scss:

.fade-1 {
  &-enter-active, &-leave-active {
    transition: all 1s;
  }

  &-enter-from, &-leave-to {
    opacity: 0;
  }
}
Artur Müller Romanov
  • 4,417
  • 10
  • 73
  • 132

1 Answers1

1

I think your second example does not work mainly because v-if is placed on element that is not a direct child of transition-group

In the comments I recommended the example from Vue 3 docs Staggering List Transitions and I still think this is one way to implement it

this explains how to animate elements of the v-for parent, after it was created but I need to animate it while it's created

Well not exactly. It shows how to animate "appear"/"leave" elements when the content of rendered array changes (by filter). In order to apply the animation of elements appearing after the component is 1st rendered, you just need the rendered array to be empty when the component is mounted and enable the items after short delay after mounted.

This snippet from the example does exactly that:

const mounted = ref(false)

onMounted(() => setTimeout(() => mounted.value = true, 200))

const computedList = computed(() => {
  return list.filter((item) => item.msg.toLowerCase().includes(query.value) && mounted.value)
})

Demo

Michal Levý
  • 33,064
  • 4
  • 68
  • 86