Nuxtでamp-imgのsrcを動的に変更する

エンジニア向けの記事です。めちゃくちゃニッチな内容です。amp-imgをlayoutsで使った時に画像が切り替わらないのを直すという内容です。

対象の事象

layoutsでamp-imgを使ってるけど、ページ遷移しても画像が切り替わらない

結論

画像のkeyにランダムな値を挿入して強制的に再描写させます。
※pageはpagesからアップするstateです。titleとかを上げる想定です。

layouts/任意のファイル.vue

<template>
  <div>
    <amp-img
     :key="randomKey"
     width="1.3"
     height="1"
     :src="page.src"
     alt="header"
   />
  </div>
</template>

<script>
export default {
 name: 'PageHeader',
 data() {
   return {
     randomKey: ''
   }
 },
 computed: {
   page() {
     return this.$store.state.page
   }
 },
 watch: {
   page() {
     this.randomKey = Math.random()
   }
 }
}
</script>

今回はページごとに全て違う画像を表示させる前提ですが、そうでない(同じ画像のページが複数ある)場合はpage.srcでの照合をかけてからrandomKeyを再計算させるといいでしょう。

原因

amp-imgはamp-imgに指定されたsrcを元にampがimgタグを作成します。
この動作はページ読み込み時にされるので、spaには対応しておらず、amp-imgのsrcは変わるのにimgのsrcは変わらず画像がそのままになっていました。

1. ページ読み込み時にamp-imgにsrc注入
2. amp scriptがamp-imgのsrcを元にimgタグ作成
3. ページ遷移時にamp-imgのsrc変更
4. srcが書き換わっただけなのでamp-imgは感知せず
5. imgタグは変わらないので画像は何も変わらない
という感じです。

参考までに、amp-imgのamp script作動前後のhtmlを書いておきます。

作動前

<amp-img alt="header" src="hoge" width="1.3" height="1" layout="responsive" data-amp-auto-lightbox-disable=""></amp-img>

作動後

<amp-img alt="header" src="hoge" width="1.3" height="1" layout="responsive" data-amp-auto-lightbox-disable="" class="i-amphtml-element i-amphtml-layout-responsive i-amphtml-layout-size-defined i-amphtml-layout" i-amphtml-layout="responsive" style="--loader-delay-offset:147ms !important;">
  <i-amphtml-sizer slot="i-amphtml-svc" style="padding-top: 50%;"></i-amphtml-sizer>
  <img decoding="async" alt="header" src="hoge" data-amp-auto-lightbox-disable="" class="i-amphtml-fill-content i-amphtml-replaced-content">
</amp-img>

いいなと思ったら応援しよう!