在vue.js中的数组中的项目渲染过渡之间进行延迟

时间:2018-12-10 02:43:17

标签: javascript vue.js

我正在从使用vuejs中的vuex调用的json服务中加载一组项目。项目将被带到一个数组中并在另一个组件中呈现。我尝试使用transition-group为项目单独添加一个过渡。但这没有用。所以我正在考虑逐项渲染项目和fadeIn项目,并且需要在一个项目和另一个项目之间进行延迟。 我的代码在下面

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>

1 个答案:

答案 0 :(得分:3)

使用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>