简体   繁体   中英

Make delay between item render transition in array in vue.js

I'm loading a set of items from a json service calling using vuex in vuejs. Items will be taken to a array and render in a different component. I tried using transition-group to add a transition seperately for a item. But it did not work. So i'm thinking of rendering item and fadeIn item by item and need to make a delay between one item and other item. My code is below

ProductItem.vue

<template>
  <transition name="slide-fade">
  <div class="product-container">
    <div class="product-box">
      <div class="product-image">
        <img v-bind:src="product.values['3'].value" alt>
      </div>
      <div class="product-details">
        <div class="product-name">{{product.values[0].value}}</div>
        <div class="product-description" v-if="product" v-html="productDescription"></div>
        <div class="product-price">From 295 LKR</div>
        <div class="product-action">
          <button class="btn-choose" @click="closeBox">
            <i class="fas fa-check fa-icon"></i> Choose
          </button>
        </div>
      </div>
    </div>
  </div>
  </transition>
</template>

Products.vue

<template>
  <div>
    <div class="product-list-container clearfix">
      <div v-if="!hasProducts">
        <product-item-loader v-for="itemLoader in 8" v-bind:key="itemLoader"></product-item-loader>
      </div>

      <transition name="fade">
        <div v-if="hasProducts">
          <product-item v-for="pItem in productsList" :product="pItem"  v-bind:key="pItem"></product-item>
        </div>
      </transition>
    </div>
  </div>
</template>

<script>
import productItem from "./ProductItem.vue";
import productItemLoader from "./ProductItemLoader.vue";
export default {
  components: {
    productItem,
    productItemLoader
  },
  data() {
    return {
      iconCalendar:
        "M39.58,115.5h70.84a7.11,7.11,0,0,0,7.08-7.08V48.21a7.11,7.11,0,0,0-7.08-7.09H99.79V34a3.54,3.54,0,0,0-7.08,0v7.08H57.29V34a3.54,3.54,0,1,0-7.08,0v7.08H39.58a7.11,7.11,0,0,0-7.08,7.09v60.21A7.11,7.11,0,0,0,39.58,115.5Zm0-67.29H50.21v3.54a3.54,3.54,0,0,0,7.08,0V48.21H92.71v3.54a3.54,3.54,0,0,0,7.08,0V48.21h10.63V62.38H39.58Zm0,21.25h70.84v39H39.58Z",
      productsList: [],
      hasProducts: false,
      date: "2012-12-01"
    };
  },
  methods: {
    optionChanged: function(selection) {
      this.getProducts(selection.name);
    },
    getProducts: function(date) {
      self = this;
      self.hasProducts = false;
      this.restAPI
        .get("", {
          params: {
            after: date,
            until: date,
            language: "en"
          }
        })
        .then(function(response) {
          self.productsList = response.data.content.classes[0].objects;
          self.productsList.length > 0
            ? (self.hasProducts = true)
            : (self.hasProducts = false);
        })
        .catch(e => {
          console.log(e);
        });
    }
  },
  beforeMount() {
    self.hasProducts = false;
    this.getProducts();
  }
};
</script>

You can achieve a nice staggered effect by using setInterval :

 new Vue({ el: '#app', data() { return { loading: false, items: [], remaining: 3000 } }, mounted() { this.loading = true const timer = () => { return setInterval(() => { this.remaining -= 1000 }, 1000) } // simulate api call const ti = timer() setTimeout(() => { const items = Array.from(Array(9), (x, i) => { return { name: `Product ${i + 1}`, description: `Product ${i + 1} description` } }) clearInterval(ti) this.loading = false const interval = setInterval(() => { if (!items.length) { clearInterval(interval) } else { this.items.push(items.shift()) } }, 360) }, 3000) }, methods: { renderNext(item) { this.items.push(item) } } }) 
 li { width: 30%; padding: .3rem; } li.striped { background-color: rgba(128,203,196,.4); } .list-complete-item { transition: all 1s; display: inline-block; margin-right: 0px; } .list-complete-enter, .list-complete-leave-to /* .list-complete-leave-active below version 2.1.8 */ { opacity: 0; transform: translateY(30px); } .list-complete-leave-active { position: absolute; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <h1 v-if="loading">Loading... {{ remaining / 1000 }}</h1> <transition-group name="list-complete" tag="ul"> <li v-for="(item, i) in items" v-bind:key="item.name" :class="`list-complete-item ${i % 2 === 0 ? 'striped' : ''}`"> <span>{{ item.name }}</span><br/> <span class="description">{{ item.description }}</span> </li> </transition-group> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM