Vue.jsをTypeScriptで利用するためのメモ

# 目的

Vue CLI 3を用いたテンプレートからVue.js+TypeScriptの実装方法および推奨スタイルを学ぶ

# プロジェクトの作成

### 前提
* Node.jsがインストールされていること

## 手順

[公式の手順](https://jp.vuejs.org/v2/guide/typescript.html#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E4%BD%9C%E6%88%90)どおりにコマンドを実行すればOK

### Vue CLI 3のインストール(初回のみ)
* `vue`コマンドが有効になる

```
npm install --global @vue/cli
```

### プロジェクト作成
* プロジェクト作成パラメータを選択する対話が始まる
* ネットワークから必要なファイルがダウンロードされ、実行ディレクトリ直下に`my-project-name`ディレクトリが作成される

```
vue create my-project-name
```

### パラメータ選択
* 最初の質問(`Please pick a preset:`)で`Manually select features`を選択する
* 2つめの質問(`Check the features needed for your project:`)で`TypeScript`にチェックをつける(他の選択肢はお好みで。自分はLinterも選択)
* 3つめの質問(`Use class-style component syntax? (Y/n)`)で`Y`を選択(`Y`がデフォルトなのでそのままEnterを押してOK)
* 残りはお好みで(自分はすべてデフォルトのまま)

```
Vue CLI v3.8.2
? Please pick a preset: Manually select features
? Check the features needed for your project: TS, Linter
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? No
? Pick a linter / formatter config: TSLint
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)Lint on save
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
```

### 作成結果確認

メッセージに従ってプロジェクトディレクトリでコマンド実行

```
cd my-project-name
npm run serve
```

`http://localhost:8080/`で起動した旨のメッセージが表示されるのでブラウザで当該URLにアクセスするとVueのデモ画面が表示される。

## テンプレートコードをみてみる

大量のファイルが作成されるが画面作成上で重要なのは以下の2ファイル

* src/App.vue
  * ルートコンポーネント
  * このファイルに作成したコンポーネントを追加していく
* src/components/HelloWorld.vue
  * 子コンポーネントのサンプル
  * このファイル自体は後で削除してOK

```html:App.vue
<template><!-- s1 -->
  <div id="app"> <!-- r1 -->
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/><!-- s2, s3, r2 -->
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from './components/HelloWorld.vue';

@Component({ // r3
  components: {
    HelloWorld, // r4
  },
})
export default class App extends Vue {} // r5
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

```html:HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <!-- 中略 -->
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

@Component
export default class HelloWorld extends Vue { // s4
  @Prop() private msg!: string;
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped> /* s5 */
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

```

### Vueのルールについて

Vue.jsの使用、およびTypeScript(クラススタイル)との連携のための書式のポイントを以下に示す。

|||
|---|---|
|r1|`<template>`タグに入れるDOM要素は1つだけ(2つ以上あるとエラーになる)|
|r2|子コンポーネントはクラス名をタグ名として標準のDOM要素と同様に記述する|
|r3|Vueコンポーネントには`@Component`アノテーションを付与する|
|r4|子コンポーネントを使用する場合はそのクラス名を`components`要素に追加する
|r5|コンポーネントとなるクラスは`Vue`クラスをextendする|

### Vueの推奨スタイル

[Vue.js公式のスタイルガイド](https://jp.vuejs.org/v2/style-guide/index.html)から、テンプレートファイルにみられるスタイルを抜粋して紹介する。

|||
|---|---|
|s1|vueファイルには上から`<template>`,`<script>`,`<style>`の順に記述する(推奨)|
|s2|単一ファイルコンポーネント(.vueファイル形式)の場合、Vueコンポーネントの場合は自己終了形式(`<MyComponent/>`)で記述する(強く推奨)|
|s3|単一ファイルコンポーネントの場合、VueコンポーネントはPascalCaseで記述する(強く推奨)|
|s4|ルートコンポーネント`App`やVueが提供するビルドインコンポーネントを除き、Vueコンポーネントは複数単語で記述する(必須)|
|s5|ルートコンポーネントやレイアウトコンポーネントを除き、コンポーネント内スタイルのスコープは同一ファイルのみにする(必須)  `scoped`属性ではなくCSS modulesやBEMを用いてもOK|

上記以外にも「優先度A:必須」～「優先度D:使用注意」まで詳細なスタイルガイドがあるため、一読すべき。

# BookMark

お世話になっているサイト

* [vue.js + typescript = vue.ts ことはじめ](https://qiita.com/nrslib/items/be90cc19fa3122266fd7)
  * Vue.js + TypeScript(クラススタイル)の基本的な書き方がだいたい紹介されている
* [TypeScriptでVue.jsを書く – Vue CLIを使った開発のポイントを紹介|maesblog](https://mae.chab.in/archives/60167)
  * 中段の「TypeScriptでVueを書くときのポイント」で紹介されているJSとTSのコード比較を参考にするとVue.js公式やVueのライブラリで説明されているJSのサンプルコードをTSに読み替えられる