Vue SSR (Nuxt) での Youtube 埋め込みでローディングを表示する

Published: 2022/6/20


Vue ないし Nuxt において Youtube の埋め込みを行おうとすると、大体は vue-youtube を利用する方法が案内される。 vue-youtube を利用する場合、これは iframe を埋め込むことになるので、 Youtube のページの読み込みが完了するまで、その部分は真っ白なページが表示されることになる。 これは、デザイン的にあまりイケていないので、読み込みの最中はローディングの画面を表示しておくようにした際の忘備録。

メモその1

vue-youtube のコンポーネントは、その $el に対して、 iframe への置き換えを行う。 結果、 vue-youtube のコンポーネントは、 render の結果と dom が不整合になり、例えば、 vue-youtube のコンポーネントに対して直接v-show を実行しようとしても、操作する対象の $el が既に document から外されてしまっているので、これが上手く働かない。

対応策としては、 vue-youtube をラップするコンテナの div を用意し、そのコンテナに対して v-show などの操作を行うことで、この問題を回避できる。

メモその2

vue-youtube には fit-parent という prop があり、これを指定しておくと、親コンポーネントの幅に合わせて iframe の幅を調整してくれる。

結果のコンポーネント

<template>
  <div class="app-youtube">
    <div v-show="loaded" class="youtube-container" >
      <VueYoutube :video-id="videoId" fit-parent @ready="onReady" />
    </div>
    <div v-if="!loaded" class="loading">
      <AppLoading />
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
// @ts-ignore
import { Youtube as VueYoutube } from 'vue-youtube'
import AppLoading from '~/components/AppLoading.vue'

export default Vue.extend({
  components: { VueYoutube, AppLoading },
  props: {
    videoId: {
      type: String,
      required: true
    }
  },
  data: () => ({
    loaded: false,
  }),
  methods: {
    onReady() {
      this.loaded = true
    }
  }
})
</script>

<style scoped>
.app-youtube {
  width: 100%;
}

.youtube-container {
  display: flex;
  width: 100%;
}

.loading {
  display: flex;
  justify-content: center;
  align-items: center;
  aspect-ratio: 16 / 9;
  width: 100%;
}
</style>

Tags: vuenuxtyoutube

関連記事

About

エンジニアです。 仕事では Xincere Residence を作っています。 このサイトは個人のブログであり、所属団体の意見等とは関係がありません。

Tags