ローディングと高さのアニメーション

デモ

使用している主な機能

算出プロパティ computed 120ページ

ウォッチャ watch 128ページ

nextTick 143ページ

コンポーネント 146ページ

動的コンポーネント 185ページ

トランジション 194ページ

ソースコード

index.vue
<template>
  <div class="example-loading example">
    <p><button @click="loadContent" :disabled="!list.length">コンテンツをリロード</button></p>
    <!-- ボーダー付きのラッパーレイヤー -->
    <div class="flexbox-wrapper" :style="{height: height+'px'}">
      <!-- トランジション & $refs.body -->
      <ul class="flexbox-body" ref="body">
        <li v-for="item in list" :key="item.id">
          {{ item.name }} {{ item.price }}
        </li>
      </ul>
      <transition>
        <Loading v-if="!list.length"/>
      </transition>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
import Loading from './Loading.vue'
export default {
  components: { Loading },
  data() {
    return {
      height: 0,
      list: []
    }
  },
  // ウォッチャ
  watch: {
    list() {
      // nextTick
      this.$nextTick(() => {
        // $refs
        this.height = this.$refs.body.getBoundingClientRect().height
      })
    }
  },
  methods: {
    loadContent() {
      this.list = []
      axios.get('/data/list.json').then(response => {
        setTimeout(() => {
          this.list = response.data
        }, 1500)
      })
    }
  },
  created() {
    this.loadContent()
  }
}
</script>

<style scoped>
.flexbox-wrapper {
  position: relative;
  border: 2px solid #ccc;
  border-radius: 4px;
  overflow: hidden;
  transition: height .4s;
  min-height: 3em;
}
.flexbox-body {
  margin: 0 0 0 24px;
  padding: 16px;
}
/* トランジション用スタイル */
.v-enter-active, .v-leave-active {
  transition: opacity .4s;
}
.v-enter, .v-leave-to {
  opacity: 0;
}
</style>
LoadContent.vue
<template>
  <div class="before-load-content">
    LOADING NOW
  </div>
</template>

<style scoped>
.before-load-content {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: #bbb;
}
</style>

コメント

Katashin さんの vue-size-provider を利用すると、要素の高さを監視して簡単に高さのアニメーションを適用できます。