【Vue】componentタグの便利な使い方。変数によるtemplateの出し分けと、生HTMLの生成

vueの`componentタグ`を使うとv-bindの属性`:is`で指定した値に合わせてtemplateを出し分けることができる。

また、文字列を直接指定（または戻り値で文字列を返す）すると、その文字列に合わせてたタグを生成することができる。


##目次

1. [文字列で指定](#文字列で指定)
    2. [文字列で直接指定](#文字列で直接指定)
    3. [変数を指定し文字列を返す](#変数を指定し文字列を返す)
4. [テンプレートを指定](#テンプレートを指定)
5. [他の属性も合わせて指定する方法](#他の属性も合わせて指定する方法)


<br>
##文字列で指定

###文字列で直接指定
`:is`でタグ名を指定するとそのタグが生成される。

**▼divタグを指定した場合**

```vue:
<template>
    <div>
      <component :is="'div'">
        テスト
      </component>
    </div>
</template>
```

<br>
**▼ブラウザの表示**

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/f7f74d85-1597-d271-c8e9-14ec7c8cff6d.png)|
|:--|


**▼ポイント**
重要なポイントは文字列で指定すること。そのためには**シングルクオテーションで囲む**。

`:is="'div'"`

<br>
**▼エラーになる場合**
シングルクオテーションで囲まないと**変数として認識される**。変数で指定する場合は、export default内に定義する必要がある。

`:is="div"`と記述してexport default内にdivの定義がない場合はエラーとなる。


>[Vue warn]: Property or method "div" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.




<br>
###変数を指定し文字列を返す
`:is`で変数を指定し、dataやcomputed, methodで文字列を返してもタグを指定できる。

**▼変数を指定（dataでpタグを指定）**

```vue:
<template>
    <div>
      <component :is="assignTag">
        テスト
      </component>
    </div>
</template>

<script>
export default {
  data(){
    return{
      assignTag: "p"
    }
  }
}
</script>
```

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/f81534e3-4e4f-bb82-0e88-99278c0ffaac.png)|
|:--|




<br>
##テンプレートを指定

テンプレートを指定する場合は以下３つの手順が必須。

1. テンプレートを読み込む
2. テンプレートをローカルに登録
3. 属性の値に変数を指定
4. 変数の値にケバブケースに変換したテンプレ名を指定


###1. テンプレートを読み込む
例えば、同じ階層にある TmpAddColumn.vue を読み込む場合

```vue:
<script>
import  TmpAddColumn from  './TmpAddColumn'
</script>
```

<br>
###2. テンプレートをローカルに登録
テンプレートを読み込んだら、ローカル(vue)に登録する。

```vue:
<script>
import  TmpAddColumn from  './TmpAddColumn'

export default {
  components: {
    TmpAddColumn,
  }
}
</script>
```


<br>
###3. 属性の値に変数を指定
`:is`の値に変数を指定する。変数名は任意。

```vue:
<template>
    <div>
      <component :is="assignTemplate">
        テスト
      </component>
    </div>
</template>
```



<br>
###4. 変数の値にケバブケースに変換したテンプレ名を指定

属性で指定した値とテンプレートを紐づけるためには、テンプレート名をケバブケース（ハイフンで繋ぐ）に変換した値を属性に指定する。

```vue:
<script>
import  TmpAddColumn from  './TmpAddColumn'

export default {
  components: {
    TmpAddColumn,
  },
  data(){
    return {
      assignTemplate: "tmp-add-column"
    }
  }
}
</script>
```

以上の処理で、
属性の値　->　dataの値 -> template　の順でつながる。

<br>
**▼ブラウザの表示**

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/cc120deb-94c7-1a59-0c90-135d3d0b9c89.png)|
|:--|


<br>
##他の属性も合わせて指定する方法
`:is`の他に`v-bind`を使うと他の属性を指定することができる。

widthなどを簡単に調整できる。

**▼width, colspan, rowspanを追加**

```vue:
<template>
    <div>
      <table border="1px">
        <tr>
          <component :is="'th'" v-bind= "{width: Width,  conspan: colSpan, rowspan: rowSpan }">
            テスト
          </component>
        </tr>
      </table>
    </div>
</template>

<script>
import  TmpAddColumn from  './TmpAddColumn'

export default {
  components: {
    TmpAddColumn,
  },
  data(){
    return {
      assignTemplate: "tmp-add-column",
      Width: "50%",
      colSpan: 3,
      rowSpan: 2
    }
  }
}
</script>
```


|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/40bd7143-e364-742c-d11a-6935ae97ff9e.png)|
|:--|

HTMLに指定した属性が追加されている。

```html
<th width="50%" conspan="3" rowspan="2">
        テスト
</th>
```