TypeScriptベースでVue.jsを書く

#はじめに
おはようございます。こんにちは。こんばんは。
Watatakuです。
今回は[Vue.jsでTypeScriptを始めよう(はじめかた)](https://qiita.com/watataku/items/eadcb4a26ff8b8486942)の続きなのですが[前の章](https://qiita.com/watataku/items/fa6ba97f6f394e693df7)でTypeScriptの書き方が大体分かったのでTypeScriptベースでVueアプリを作っていきます。

*この記事はの対象者はVueを勉強しているけど「TypeScriptベースでアプリを構築したい！」という方へ向けて書いております。*

#基本の書き方
ではまずはじめに実際にコードを用いて解説していきます。

```vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>{{ this.count }}</h2>
    <button @click="countUp">increment</button>
  </div>
</template>

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

@Component
export default class HelloWorld extends Vue {
  @Prop() private msg!: string;

  private count: number = 0;

  public countUp(): void {
    this.count++;
  }
}
</script>
```

上記サンプルコードでは、ボタンをクリックするたびにカウンタの値が一つづつ増えていくものです。
今回はこちらのコードで基本の解説をしていきます。

まず最初に、``private count: number = 0;``です。
この部分は

```
data() {
  return {
    count: 0
  }
}
```
と同じになります。

##propsの受け取りと書き方
※``msg="Welcome to Your Vue.js + TypeScript App"``と言う文字列がpropsとして送られてくるとして解説します。
まずは**Props**を``vue-property-decorator``からインポートします。

```js
import { Prop } from 'vue-property-decorator';
```
受け取りかたは

```js

@Prop() private msg!: string;
```
このように書くと親から送られてきたprops(Welcome to Your Vue.js + TypeScript App)を受け取ることができます。
因みに名称に「!」を付与する必要があります。

##メソッドの書き方
本来なら

```
methods: {
	・・・・・・・
}
```
のようにしてmethodsの中に各々メソッドを記述していきますがそんなことは必要なくただただ**Vueクラス内でメソッドを書けばOK**です。

#その他の書き方
##算出プロパティ:computed
算出プロパティはアノテーションではなく、get構文を用いて実装します。

```js

public get doubledCount(): number {
  return this.count * 2;
}
```

##監視プロパティ:watch

ここからはスクロールの量を取得するサンプルコードを用いて解説していきます。

```vue

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <p>{{ this.scrollY }}</p>
  </div>
</template>

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

@Component
export default class About extends Vue {
  private scrollY: number = 0;

  public handleScroll(): void {
    this.scrollY = window.scrollY;
  }
  @Watch('scrollY')
  public scrollYChange(val: number, oldVal: number) {
    console.log(
      'スクロールの値が' + oldVal + 'から' + val + 'に変化しました。'
    );
  }

  private mounted(): void {
    window.addEventListener('scroll', this.handleScroll);
  }

  private destoryed(): void {
    window.removeEventListener('scroll', this.handleScroll);
  }
}
</script>

<style>
.about {
  height: 200vh;
}
</style>

```
このように**watch**を使用する時は``vue-property-decorator``による**@Watchデコレータ**によって記述しています。
※また使用する時はwatchをimportして下さい。

```js:

import { Watch } from 'vue-property-decorator'
```

```
@Watch('監視するもの', {deep: <真理値>, immediate: <真理値>})
<メソッド名>(val: データ型, oldVal: データ型) {
  // 処理
}
```

- deep : trueの場合、監視するプロパティがオブジェクトの場合ネストされた値の変更も検知します。
- immediate : trueの場合、初期読み込み時にも呼び出します

##emit
子コンポーネントから親コンポーネントにデータを渡すときに使います。

```vue:HelloWould.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 {
  @Prop() private msg!: string;

  public mounted() {
    this.$emit('flg', true);
  }
}
</script>
```

```vue:親コンポーネントファイル名

<template>
  <div class="home">
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" v-on:flg="setEmit" />
    <h2 v-if="flg">emit->できてる</h2>
    <h2 v-else>emit->できてない</h2>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Emit } from 'vue-property-decorator';
import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src

@Component({
  components: {
    HelloWorld
  },
})
export default class Home extends Vue {
  private flg: boolean = false;

  public setEmit(flg: boolean): void {
    this.flg = flg;
  }
}
</script>
```

親コンポーネントへのデータの送りかたは``this.$emit(イベント名, 送りたいもの)``

子コンポーネントから送られてきたデータの受け取りかたは
``<子コンポーネント v-on:イベント名="関数"/>`` ＋ ``関数(イベント名: データ型): 戻り値のデータ型 {}``


#ライフサイクル
ライフサイクルについては[こちら](https://qiita.com/chan_kaku/items/7f3233053b0e209ef355)をご覧ください。

```js

// ライフサイクルの書き方
public beforeCreate(): void {
  console.log('ライフサイクルbeforeCreate');
}

public created(): void {
  console.log('ライフサイクルcreated');
}

public beforeMount(): void {
  console.log('ライフサイクルbeforeMount');
}

public mounted(): void {
  console.log('ライフサイクルmounted');
}

public beforeUpdate(): void {
  console.log('ライフサイクルbeforeUpdate');
}

public updated(): void {
  console.log('ライフサイクルupdated');
}

public beforeDestroy(): void {
  console.log('ライフサイクルbeforeDestroy');
}

public destroy(): void {
  console.log('ライフサイクルdestoroy');
}
```

[参考：https://noumenon-th.net/programming/2019/07/02/class-style/](https://noumenon-th.net/programming/2019/07/02/class-style/)
以上。
#最後に
解説が浅いところとか、間違い等があると思いますのでその時はアドバイス等お願いします。

最後まで読んでいただきありがとうございました。
[Twitter](https://twitter.com/watataku9)やってます。良ければチェックして見てください。:point_up::point_up: