クマのブログ

つまづいたところ、学びを書いていきます

ライフサイクルフックの違いによるレンダリングのタイミング~img src編③~

はじめに

前回(~img src編②~)の続き

前回はv-ifの条件をurl(親のプロパティ)にしていたが、今回はchildUrl(子のdataプロパティ)にする

話すこと

前回と同じで、以下コードを例にどのライフサイクルフックをつかったら、どんな挙動を示すのかを順にみていく

やりたいこと

コンポーネントで定義するimgタグのsrc属性の内容に応じて表示する画像を変更する

OKな時

f:id:kuma_kuma0121:20220226221223p:plain

NGな時

f:id:kuma_kuma0121:20220226220839p:plain

ソースコード

親コンポ―ネント

<template>
  <div>
    <ImageChildComponent
      :url="url"
      @replace="replaceUrl"
    ></ImageChildComponent>
  </div>
</template>

<script>
import ImageChildComponent from './ImageChildComponent.vue'

export default {
  components: {
    ImageChildComponent
  },
  data() {
    return {
      url: '',
    }
  },
  methods: {
    replaceUrl(newUrl) {
      console.log(newUrl);
      this.url = newUrl;
    },
  }
}
</script>

コンポーネントでやっていることは前回と変わらない

コンポーネント

<template>
  <div>
    <!-- OK時の画像 -->
        <div
      v-if="childUrl" // 変更
    >
      <h2>OK!!!</h2>
      <img
        :src="childUrl"
        width=200
      >
    </div>
    <!-- NG時の画像 -->
    <div
      v-else
    >
      <h2>NG...</h2>
      <img
        src="../assets/no-image.png"
        width=200
      >
    </div>
  </div>
</template>

<script>
export default {
  props: {
    url: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      childUrl: '',
    }
  },
    beforeCreate() {
    console.log('beforeCreate: ', this.childUrl);
    // const newUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
    // this.childUrl = newUrl;
  },
  created() {
    console.log('created: ', this.childUrl);
    // const newUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
    // this.childUrl = newUrl;
  },
  beforeMount() {
    console.log('beforeMount: ', this.childUrl);
    // const newUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
    // this.childUrl = newUrl;
    // console.log('beforeMount: ', this.childUrl);
  },
  mounted() {
    console.log('mounted: ', this.childUrl);
    // const newUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
    // this.childUrl = newUrl;
    // console.log('mounted: ', this.childUrl);
  },
  methods: {
    getUrl() {
      console.log('methods(getUrl): ', this.childUrl);
      // const newUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
      // this.childUrl = newUrl;
      // return this.childUrl;
    }
  }
}
</script>

<template>でやっていることは基本的には一緒ですが、変化点は以下

<script>でやっていることは前回と全く一緒

懸賞方法

前回同様、コメントアウトしてある箇所を随時コメントインして実行していく

デフォルト

ブラウザ

f:id:kuma_kuma0121:20220226220839p:plain

コンソール

f:id:kuma_kuma0121:20220226221655p:plain

  • 今回はエラーがでずにchildUrlがundifiedになっている…

ギモン

  • beforeCreateの時点ではdata()は実行されていないから、前回同様「childUrlなんてない!」って怒られてもいいと思うけど、なんで今回undefinedが定義されているんだろう…

beforeCreated

...
beforeCreate() {
    console.log('beforeCreate: ', this.childUrl);
    const newUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
    this.childUrl = newUrl;
},
...

ブラウザ

デフォルトと同じなので割愛

コンソール

コチラもデフォルトと同じなので割愛

デフォルトでchildUrlを認識しているのであれば、beforeCreateでchildUrlにnewUrl代入すればDOMに反映されると思ったが、違った

created

created() {
    console.log('created: ', this.childUrl);
    const newUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
    this.childUrl = newUrl;
    console.log('created: ', this.childUrl);
},

ブラウザ

f:id:kuma_kuma0121:20220226221223p:plain

コンソール

f:id:kuma_kuma0121:20220226221757p:plain

今までで一番Vueライフサイクルのイメージ通りの挙動した

consoleもcreatedでchildUrlにnewUrlを定義した後は、全てconsole.logでnewUrlの値が出力できている

beforeMount

beforeMount() {
        console.log('beforeMount: ', this.childUrl);
    const newUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
    this.childUrl = newUrl;
    console.log('beforeMount: ', this.childUrl);
},

ブラウザ

createdと同じ

コンソール

f:id:kuma_kuma0121:20220226221842p:plain

こちらも想定通り

boforeMount以降はnewUrlが表示されている

mounted

mounted() {
        console.log('mounted: ', this.childUrl);
    const newUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
    this.childUrl = newUrl;
    console.log('mounted: ', this.childUrl);
},

ブラウザ

created, beforeMouteと同じ

コンソール

f:id:kuma_kuma0121:20220226221911p:plain

mountedでnewUrlをchildUrlに代入しているので、mountedでdataが変更されたタイミングでre-renderingされ、mountedでconsoleに表示される

methods

ここで想定するのは以下のようなソースコード

<template>
        <div
      v-if="url"
    >
      <h2>OK!!!</h2>
      <img
        :src="getUrl()" // 変更
        width=200
      >
    </div>
        ...
</template>

<script>
export default {
    ...,
    methods: {
        getUrl() {
                console.log('methods(getUrl): ', this.childUrl);
          const newUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
          this.childUrl = newUrl;
          return this.childUrl;
      }
        ...
}
</script>

ブラウザ

f:id:kuma_kuma0121:20220226220839p:plain

コンソール

f:id:kuma_kuma0121:20220226222015p:plain

  • v-ifで表示childUrlがnullなので、常にno-imageが表示される

getUrlをv-ifで呼び出した場合

     
        <div
      v-if="getUrl()"  <!-- 変更 -->
    >
      <h2>OK!!!</h2>
      <img
        :src="getUrl()"
        width=200
      >
    </div>

ブラウザ

f:id:kuma_kuma0121:20220226221223p:plain

コンソール

f:id:kuma_kuma0121:20220226222058p:plain

前回同様で

  • mountedまでは1回めのDOM生成時(v-if, imgのsrc属性)のgetUrl呼び出し時のconsole
  • mounted以降は2回目のDOM生成時のgetUrl呼び出し時のconsole

の出力結果

参考記事

https://jp.vuejs.org/v2/guide/instance.html#ライフサイクルダイアグラム

所見

  • createdでdataプロパティの値を変更するとそれ以降のライフサイクルフックでも変更後の値が取得できる点から、一番Vueのライフサイクル通りの挙動をしていた
  • 前回同様、最後のgetUrの例はライフサイクルを知るのにかなりわかりやすかった
  • imgのsrcの変遷を追うことでだいぶ理解はできたと思う