Vue.jsでFacebookのようなローディングを表示する [vue-content-loaderの紹介]

FacebookやYoutubeなどで最近良く見かけるコンテンツローダーを手軽に実装できるvue-content-loaderの紹介です。
簡単に導入できてSPAぽいリッチな表現ができるのでおすすめです。

以下のようなものを作成します。
（GIFの都合上カクついてますが、実際はもっとなめらかです。）
![Jan-13-2019 17-52-20 (1).gif](https://qiita-image-store.s3.amazonaws.com/0/114396/cdd56b6d-8cbd-5143-59a6-f37989c0b97e.gif)



# vue-content-loaderのインストール
https://github.com/egoist/vue-content-loader
を利用します。Reactにあるreact-content-loaderのvue版のようです、
Vueプロジェクト上で、パッケージを追加します。

```bash
$ yarn add vue-content-loader
```
# 実装サンプル
あとは、importして使うだけです。
LoadingBlogSectionコンポーネントというものを作成します。
見栄えを整えるため、vuetify (https://vuetifyjs.com/en） を使っています。

```vue:LoadingBlogSection.vue

<template lang="pug">
  v-container(grid-list-lg fluid pa-0)
    v-layout(row wrap)
      v-flex(v-for="n in 4" :key="n" xs12 md3)
        v-card
          content-loader(:width="300" :height="300")
            rect(width="100%" height="150")
            rect(y="180" x="15" width="150" height="20")
            rect(y="220" x="15" width="200" height="10")
            rect(y="240" x="15" width="250" height="10")
            rect(y="260" x="15" width="150" height="10")
            rect(y="280" x="15" width="250" height="10")
</template>

<script>
import { ContentLoader } from 'vue-content-loader'

export default {
  components: {
    ContentLoader
  }
}
</script>
```

以下部分でContentLoaderの読み込みと、componentsへの登録を行います。

```vue
<script>
import { ContentLoader } from 'vue-content-loader'

export default {
  components: {
    ContentLoader
  }
}
</script>
```

次にLoader表示部分です。
content-loader内部のrectというコンポーネントで四角のSVGを表示しています。
yが上部からの絶対位置、xが左部からの絶対位置です。

```vue
<template lang="pug">
...
        v-card
          content-loader(:width="300" :height="300")
            rect(width="100%" height="150")
            rect(y="180" x="15" width="150" height="20")
            rect(y="220" x="15" width="200" height="10")
            rect(y="240" x="15" width="250" height="10")
            rect(y="260" x="15" width="150" height="10")
            rect(y="280" x="15" width="250" height="10")
...
```

これでローディング用のコンポーネントが出来たので、
あとは、v-ifでローディング状態を判定して、ローディング中のみ表示するようにすればOKです。
以下Apolloの例で、`$apollo.loading`でローディング状態を判定しています。
BlogSectionがAjaxで取得したデータの表示用のコンポーネントです。

```vue:index.vue
<template lang="pug">
  v-content
    v-container
      h1(class="mb-5") vue-content-loader demo
      <!-- この部分でv-ifで判定して、表示を切り替えている -->
      BlogSection(:posts="posts" v-if="!$apollo.loading")
      LoadingBlogSection(v-if="$apollo.loading")
</template>

<script>
import { FETCH_POST_BY_LIMIT } from '@/apollo/query/posts'
import BlogSection from '@/components/BlogSection'
import LoadingBlogSection from '@/components/LoadingBlogSection'

const POSTS_LIMIT = 4

export default {
  components: {
    BlogSection,
    LoadingBlogSection
  },
  apollo: {
    posts: {
      query: FETCH_POST_BY_LIMIT,
      variables () {
        return {
          first: POSTS_LIMIT
        }
      }
    }
  }
}
</script>
```

これで完成です。


# 参考： ローディングのSVGをGUIで調整する
svgで表示する部分は、以下サイトにてGUI上で調整が行えます。
https://create-vue-content-loader.netlify.com/
完了したら、左ペインのコードをコピペして使ってください。

<img width="1348" alt="スクリーンショット 2019-01-13 17.54.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/114396/4547d759-99a8-feda-5f6a-ed082204740f.png">