LoginSignup
3
3

More than 1 year has passed since last update.

【Vue.js】動的にコンポーネントを切り替える際に、切り替え毎にdestroyedされないようにするには

Last updated at Posted at 2021-06-01

はじめに

仕事で使う事になったので1からVue.jsについて学んだ。
ちゃんと覚えておかないとまずそうな事を備忘録として1つ1つ残しておく。

動的にコンポーネントを切り替える際に、切り替え毎にdestroyedされないようにするには

動的なコンポーネントの切り替えについて

<component></component>タブとv-bind:is=""(v-bindディレクティブのis属性)を用いる事で以下の動画のように動的にコンポーネントを切り替える事ができる。
ezgif.com-gif-maker (7).gif
動画のソースコードは以下。

App.vue
<template>
  <div>
    <!-- 省略 -->
    <button @click="currenComponent = 'Home'">Home</button>
    <button @click="currenComponent = 'About'">About</button>
    <component :is="currenComponent"></component>
  </div>
</template>

<script>
import LikeHeader from "./components/LikeHeader.vue";
import About from "./components/About";
import Home from "./components/Home";

export default {
  // 省略
  components: {
    LikeHeader,
    About,
    Home,
  },
  // 省略
};
</script>

<style scoped>
/* 省略 */
</style>
About.vue
<template>
  <p>About</p>
</template>
Home.vue
<template>
  <p>Home</p>
</template>

ソースコード全体は以下。

動的なコンポーネント切り替えでは、切り替え毎にコンポーネントがdestroyedされる

Vue.jsの仕様として、コンポーネントを切り替えるとその度にコンポーネントがdestroyedされる。
ezgif.com-gif-maker (8).gif
動画のソースコードは以下(App.vue上記と同じ)。

About.vue
<template>
  <p>Home</p>
</template>

<script>
export default {
  destroyed() {
    console.log("Home destroyed");
  },
};
</script>
Home.vue
<template>
  <div>
    <p>About</p>
    <input type="text" />
  </div>
</template>

<script>
export default {
  destroyed() {
    console.log("About destroyed");
  },
};
</script>

ソースコード全体は以下。

コンポーネントを切り替えると自動的に前のコンポーネントは破棄されてなくなるので、いちいちdestroyedする必要がなくなり基本的には都合がいい。
ただ、この仕様で困るのは、
コンポーネントのデータは保持しておきたいといった場面で、タブ切り替えで動的にコンポーネントが切り替えた際に、コンポーネントのデータが消えてしまうという事。
これを防ぐ(動的にコンポーネントを切り替えてもdestroyedされないようにする)のに<keep-alive></keep-alive>タグを使う。

<keep-alive></keep-alive>タグで囲む事でdestroyedされないようにできる

<<keep-alive></keep-alive>>タグでラップ(囲む)だけでOK。
ezgif.com-gif-maker (9).gif
動画のソースコードは以下(About.vueHome.vue上記と同じ)。

App.vue
<template>
  <div>
    <!-- 省略 -->
    <button @click="currenComponent = 'Home'">Home</button>
    <button @click="currenComponent = 'About'">About</button>
    <keep-alive>
      <component :is="currenComponent"></component>
    </keep-alive>
  </div>
</template>

<script>
import LikeHeader from "./components/LikeHeader.vue";
import About from "./components/About";
import Home from "./components/Home";

export default {
  // 省略
  components: {
    LikeHeader,
    About,
    Home,
  },
  // 省略
};
</script>

<style scoped>
/* 省略 */
</style>

ソースコード全体は以下。

上記のようにする事でdestroyedが実行されなくなるのでコンポーネントのデータも保持されるようになる。
ただこの時、通常のVueインスタンスのライフサイクルフックが使えないが、この時はactivated・deactivatedを使う。

<keep-alive></keep-alive>を使っている時のライフサイクルフック

keep-aliveを使っている時には、以下のライフサイクルフックが使えるようになるので、それらを使って「~の時に」という実装をするようにする。

ライフサイクルフック 説明
activated コンポーネントがDOMに表示される時に~
deactivated コンポーネントがDOMに表示されなくなった時に~

ezgif.com-gif-maker (10).gif

動画のソースコードは以下(App.vue<keep-alive></keep-alive>タグで囲む事でdestroyedされないようにできると同じ)。

ソースコード全体は以下。

Vue.jsの勉強メモ一覧記事へのリンク

Vue.jsについて勉強した際に書いた勉強メモ記事のリンクを集約した記事。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3