【Vue.js】Vue CLI 3 + tsx

# :tools: セットアップ
## Vue CLI 3 でテンプレート生成
まずは```vue create```コマンドでテンプレート生成します。

```shell
$ vue create {{ YOUR_APP_NAME }}
```
- ```Babel```
- ```TypeScript```

上記2つの項目は必ずチェックを入れます。

# :inbox_tray: インストール
## vue-tsx-support をインストール
[vue-tsx-support](https://github.com/wonderful-panda/vue-tsx-support)をインストールします。
既に```Vue.js```で```tsx```を使えるライブラリが存在していました。

```shell
$ yarn add vue-tsx-support
```
# :keyboard: 開発
## コンポーネントの作成
```src/components/HelloWorld.vue``` を削除して
新たに```HelloWorld.tsx``` を作成します。

## App.vue
```App.vue``` のHelloWorldコンポーネントの呼び出し部分を修正します。

```tsx
import HelloWorld from './components/HelloWorld.vue'
``` 
↓

```tsx
import HelloWorld from './components/HelloWorld'
``` 
拡張子```.tsx``` は不要になります。

## HelloWorld.tsx
作成した```HelloWorld.tsx``` に記述していきます。

```tsx:HelloWorld.tsx
import * as tsx from 'vue-tsx-support';
import { VNode } from 'vue';

export default tsx.component({
  name: 'HelloWorld',
  render(): VNode {
    return (
      <div>
        <h1>Hello World</h1>
      </div>
    );
  },
});
```

### props

次に、```App.vue``` から```props``` で渡された```msg``` を表示します。

```tsx:HelloWorld.tsx
export default tsx.component({
  name: 'HelloWorld',
  props: {
    msg: {
      type: String,
      required: true,
    },
  },
  render(): VNode {
    return (
      <div>
        <h1>{this.msg}</h1>
      </div>
    );
  },
});
```

### if
```tsx
render(): VNode {
  return (
    <div>
      {this.isShow && <h2>Hi {this.member.name}</h2>}
    </div>
  );
}
```

```this.isShow``` が```true```の場合に後続の```<h2>``` タグが表示されます。

表示、非表示の切り替えではなく、文言を出し分けたい場合は三項演算子を使用します。

```tsx
render(): VNode {
  return (
    <div>
      {this.isMember
        ? <h2>Hi {this.member.name}</h2>
        : <h2>Hi No Name User</h2>}
    </div>
  );
}
```

### for
```tsx
render(): VNode {
  return (
    <div>
      {Object.keys(this.member).map((key: string) => (
        <p>{key}: {this.member[key]}</p>
      ))}
    </div>
  );
}
```

### CSS in JS
```tsx
render(): VNode {
  return (
    <div>
      <h1 style={styles.msg}>{this.msg}</h1>
    </div>
  );
}

const styles = {
  msg: {
    fontSize: '24px',
    color: 'red',
  },
};
```

### 全体
```tsx:HelloWorld.tsx
import * as tsx from 'vue-tsx-support';
import { VNode } from 'vue';

interface IData {
  isMember: boolean;
  member: {
    [key: string]: string | number,
    name: string,
    age: number,
    gender: string,
  };
}

export default tsx.component({
  name: 'HelloWorld',
  props: {
    msg: {
      type: String,
      required: true,
    },
  },
  data(): IData {
    return {
      isMember: true,
      member: {
        name: 'Caroline',
        age: 22,
        gender: 'female',
      },
    };
  },
  render(): VNode {
    return (
      <div>
        <h1 style={styles.msg}>{this.msg}</h1>
        {this.isMember
            ? <h2>Hi {this.member.name}</h2>
            : <h2>Hi No Name User</h2>}
        {Object.keys(this.member).map((key: string) => (
          <p>{key}: {this.member[key]}</p>
        ))}
      </div>
    );
  },
});

const styles = {
  msg: {
    fontSize: '24px',
    color: 'red',
  },
};

```

# :pencil2: 最後に
```Vue CLI``` と ```vue-tsx-support``` のおかげで簡単にVue.js + tsx環境が出来上がりました。
作者の方々に感謝です。

```tsx``` の```if``` や```for``` は、好みの問題かもしれませんが、```Vue.js``` の```<template>``` に```v-if``` や ```v-for``` を記述するよりかは、可読性が上がる気がします。

簡単に導入できるため、一度お試しすることをオススメします。

以上