0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TypeScript+Vue の環境で動的コンポーネント

Last updated at Posted at 2019-06-27

概要

Vue + TypeScript の環境で v-bind:is による動的コンポーネントの扱い方について調べたところ、あまり情報が見つからなかったので、色々試して 2パターンの解決法を見つけたのでメモ。

動的コンポーネントについてはこちら:コンポーネントの基本 — Vue.js

開発環境

TypeScript (3.4.3)
Vue (2.6.10)

(カッコ内は記事を書いている時のバージョン)

JavaScript での例

<template>
  <div>
    <ul class="tabs">
      <li @click="changeChild('hoge')">Hoge</li>
      <li @click="changeChild('fuga')">Fuga</li>
    </ul>
    <component :is="currentChild" />
  </div>
</template>

<script>
import HogeHoge from "HogeHoge.vue";
import FugaFuga from "FugaFuga.vue";

export default {
  data: function(){
    return {
      currentChild: HogeHoge
    };
  },
  components: {
    HogeHoge,
    FugaFuga
  },
  methods: {
    changeChild(name) {
      this.currentChild = name === "hoge" ? HogeHoge : FugaFuga;
    }
  }
};
</script>

TypeScript の場合

方法その 1: バインドする変数の型を any にする。

<template>
  <div>
    <ul class="tabs">
      <li @click="changeChild('hoge')">Hoge</li>
      <li @click="changeChild('fuga')">Fuga</li>
    </ul>
    <component :is="currentChild" />
  </div>
</template>

<script lang="ts">
  import HogeHoge from "HogeHoge.vue";
  import FugaFuga from "FugaFuga.vue";
  import { Component, Vue } from "vue-property-decorator";

  @Component({
    components: {
      HogeHoge,
      FugaFuga
    }
  })
  export default class OurParent extends Vue {
    currentChild: any = HogeHoge;

    changeChild(name) {
      this.currentChild = name === "hoge" ? HogeHoge : FugaFuga;
    }
  }
</script>

こうすると JavaScript と同じように import してきたコンポーネントをそのまま突っ込めますが、any に逃げる形になってしまいます。

方法その 2: バインドする変数の型を string にして、コンポーネント名で指定。

<template>
  <div>
    <ul class="tabs">
      <li @click="changeChild('hoge-hoge')">Hoge</li>
      <li @click="changeChild('fuga-fuga')">Fuga</li>
    </ul>
    <component :is="currentChild" />
  </div>
</template>

<script lang="ts">
  import HogeHoge from "HogeHoge.vue";
  import FugaFuga from "FugaFuga.vue";
  import { Component, Vue } from "vue-property-decorator";

  @Component({
    components: {
      HogeHoge,
      FugaFuga
    }
  })
  export default class OurParent extends Vue {
    currentChild: string = "hoge-hoge";

    changeChild(name) {
      this.currentChild = name;
    }
  }
</script>

個人的にはこちらの方がインスペクター上で判別のしやすく、JavaScript での対応方法としても挙げられているので、良いと思います。

(こっちの方法は、最初 components に子コンポーネントを登録し忘れて若干詰まった、という話もあったりなかったりします。)

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?