Nuxt TypeScript + Vue Property Decorator によるカウンターのサンプルコード

## 概要

- Nuxt TypeScript + Vue Property Decorator を使用して「+」「-」ボタンで数値が増減するカウンターを作成する

## 今回の環境

- Node.js 13.12.0
- Nuxt.js 2.12.2
- TypeScript 3.8.3
- Nuxt TypeScript (Nuxt.js 向け TypeScript サポート)
- Vue Property Decorator 8.4.1

## Nuxt TypeScript + Vue Property Decorator によるカウンターのサンプルコード

### ソースコード一覧

```
├── nuxt.config.ts
├── package-lock.json
├── package.json
├── pages
│   └── index.vue
├── tsconfig.json
└── vue-shim.d.ts
```

### nuxt.config.ts

nuxt.config.js の TypeScript 版。

```ts
import { Configuration } from '@nuxt/types'

const config: Configuration = {
  buildModules: ['@nuxt/typescript-build']
}
export default config
```

### package.json

必要なライブラリの記述等。

```json
{
  "name": "my-app",
  "scripts": {
    "dev": "nuxt-ts",
    "build": "nuxt-ts build",
    "generate": "nuxt-ts generate",
    "start": "nuxt-ts start"
  },
  "dependencies": {
    "@nuxt/typescript-runtime": "0.4.1",
    "nuxt": "2.12.2",
    "vue-property-decorator": "8.4.1"
  },
  "devDependencies": {
    "@nuxt/typescript-build": "0.6.1"
  }
}
```

### pages/index.vue

カウンター表示用のページコンポーネント。

```vue
<template>
  <div>
    <p>Data: {{ myCount }}</p>
    <p>Data: {{ myWatch }}</p>
    <p>Computed: {{ countByComputed }}</p>
    <p>
      <button @click="increment">+</button>
      <button @click="decrement">-</button>
    </p>
  </div>
</template>

<script lang="ts">

// Vue Property Decorator と Vue Class Component をインポートする
import { Vue, Component, Watch } from 'vue-property-decorator'

// Vue Class Component を使う
@Component
export default class CounterComponent extends Vue {

  // data
  myCount: number = 0
  myWatch: number = 0

  // 算出プロパティ (computed property)
  // myCount の値が更新されたときに呼び出される
  get countByComputed(): number {
    console.log('countByComputed')
    return this.myCount
  }

  // 監視プロパティ (watched property)
  // myCount の値が更新されたときに呼び出される
  @Watch('myCount')
  countByWatched() {
    console.log('countByWatched')
    // 2倍の値をセット
    this.myWatch = this.myCount * 2
  }

  // メソッド (method)
  // 「+」ボタンクリック時に呼ばれる
  increment() {
    console.log('increment')
    this.myCount++
  }

  // メソッド (method)
  // 「-」ボタンクリック時に呼ばれる
  decrement() {
    console.log('decrement')
    this.myCount--
  }
}
</script>
```

### tsconfig.json

ほぼ Nuxt TypeScript の公式資料通りだが、Vue Property Decorator (vue-property-decorator) を使うため experimentalDecorators の設定を追加している。

```json
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "target": "es2018",
    "module": "esnext",
    "moduleResolution": "node",
    "lib": [
      "esnext",
      "esnext.asynciterable",
      "dom"
    ],
    "esModuleInterop": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noEmit": true,
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./*"
      ],
      "@/*": [
        "./*"
      ]
    },
    "types": [
      "@types/node",
      "@nuxt/types"
    ]
  },
  "exclude": [
    "node_modules"
  ]
}
```

### vue-shim.d.ts

Nuxt TypeScript の公式資料通り。
Vue ファイルの型を提供するための型宣言。

```ts
declare module "*.vue" {
  import Vue from 'vue'
  export default Vue
}
```

## Node.js サーバを起動

package.json に記述したライブラリをインストール。

```
$ npm install
```

Node.js サーバを起動。

```
$ npm run dev

> my-app@ dev /Users/foobar/my-app
> nuxt-ts


   ╭─────────────────────────────────────────────╮
   │                                             │
   │   Nuxt.js v2.12.2                           │
   │   Running in development mode (universal)   │
   │                                             │
   │   Listening on: http://localhost:3000/      │
   │                                             │
   ╰─────────────────────────────────────────────╯

ℹ Preparing project for development
ℹ Initial build may take a while
✔ Builder initialized
✔ Nuxt files generated
ℹ Starting type checking service...

✔ Client
  Compiled successfully in 9.55s

✔ Server
  Compiled successfully in 7.86s

ℹ Type checking in progress...
ℹ Waiting for file changes
ℹ Memory usage: 222 MB (RSS: 305 MB)
ℹ Listening on: http://localhost:3000/
```

Web ブラウザで http://localhost:3000/ にアクセスすると「+」「-」ボタンと数値が増減するカウンター3つが表示される。

## 参考資料

- [セットアップ \| Nuxt TypeScript](https://typescript.nuxtjs.org/ja/guide/setup.html)
- [GitHub \- kaorun343/vue\-property\-decorator: Vue\.js and Property Decorator](https://github.com/kaorun343/vue-property-decorator)
- [Class Component \| Vue Class Component](https://class-component.vuejs.org/guide/class-component.html)
- [Nuxt\.js \+ Vue\.js \+ Vuex によるカウンターのサンプルコード \- Qiita](https://qiita.com/niwasawa/items/101bc39cc2949d519c13)
- [Nuxt TypeScript \+ Vuex によるカウンターのサンプルコード \- Qiita](https://qiita.com/niwasawa/items/7b02b9c8c277946a27cd)