Help us understand the problem. What is going on with this article?

VueにTypeScriptを導入する3つのやり方を比較してみた

最近TypeScriptが熱いっていう話をよく聞きますね!
っていうことで私もTypeScriptを導入するには何が必要なのか知りたくなりました。

でも、Vue.jsにTypeScriptを導入する方法が現状では3つほどあります。

  • Class Style Component
  • Vue.extend(後に知ったところObject Styleというらしい)
  • Composition API(RFC)

それぞれの方法の導入記事はよくありますが、それらを比較してみたくなりました。
という内容のLTを半年ほど前にしたのですが、登壇資料はこちらです。
VueでTypeScriptを始める 3つのStyle/3 style to start vue with typescript - Speaker Deck

今回の記事について

  • TypeScript運用経験がとても浅いので、比較しきれてないかもしれません
    • 間違っているところがあれば教えて下さい!
  • Vuexについては扱いません
  • VueCLI v3で作ったプロジェクトで試しています

今回のコードの比較対象

vue.js + typescript = vue.ts ことはじめ - Qiita

この記事のコードを一度JavaScriptで書いて、
それからTypeScript化するという方法を試しました

コードはこちらにあります。(リポジトリ名が適当すぎた…)
fruitriin/vue-ts-test - GitHub
vue-ts-test/Home.vue at master · fruitriin/vue-ts-test
vue-ts-test/MyButton.vue at master · fruitriin/vue-ts-test
vue-ts-test/ResetButton.vue at master · fruitriin/vue-ts-test

Class Style Component

Step by stepで書かれているし、元になった記事なので、この記事のほうが詳しいのですが…
vue.js + typescript = vue.ts ことはじめ - Qiita

既存のVue CLI v3のプロジェクトがある場合、vue add typescript でTypeScriptの関連モジュール一式がインストールできます。
対話形式で質問に答えてください。
Class Style Componentの場合は、「Use class-style component syntax?」 にYESです。

Class Style Componentで書き換える必要があるのは主に以下の通りです。

1.<script><script lang=ts>に書き換える
2.vue-property-decoratorから型注釈をimportする

スクリーンショット 2020-01-24 17.08.34.png

3.export defaultexport default class {Class名} extends Vueに書き換える
4.classのすぐ上に@Componentデコレータを付ける
5.子コンポーネントがある場合は@Component()デコレータの中に移動する
スクリーンショット 2020-01-24 17.10.07.png

5.dataはClassのプロパティとして定義する
スクリーンショット 2020-01-24 17.12.06.png

6.propsは@Propデコレータ付きのプロパティとして定義する
スクリーンショット 2020-01-24 17.13.00.png

7.$emitは@Emit()デコレータ付きのメソッドにする
イベントの送出用に別のメソッドに分ける
スクリーンショット 2020-01-24 18.10.12.png

8.computedはクラスのgetterメソッドにする
スクリーンショット 2020-01-24 18.13.07.png

9.watchは@Watch()デコレータ付きのメソッドにする
スクリーンショット 2020-01-24 18.13.37.png

Class Style ComponentでのHome.vue, MyButton.vue, ResetButton.vueのコードはこちら
vue-ts-test/Home.vue at master · fruitriin/vue-ts-test
vue-ts-test/MyButton.vue at master · fruitriin/vue-ts-test
vue-ts-test/ResetButton.vue at master · fruitriin/vue-ts-test
かなり書き方が変わりますね。

Class Style Componentポイント

  • TypeScriptっぽい書き方になる
  • Vueの公式サブプロジェクト
  • Vue.js v0.0.1の頃からあるらしく、資料が豊富
    • Vue3以降、新しい情報が出てきにくくなる可能性はある
  • Vue3.xの本体に取り込まれることはない(RFCは提出されたがRejectされた)が、3.x以降もサポートされ続ける予定らしい(というのをどこかでみた?UIT Insideで聞いた?)
  • 後述のVue.extend(Object Style)と混在させても特に問題はないはず

Vue.extend(Object Style?)

[Vue+TypeScript] Vue.extend で Vue らしさを保ちつつ TypeScript で書くときの型宣言についてまとめた - Qiita
この記事が詳しいです。

vue add typescript して、Use class-style component syntax?にNOと答えます

1.<script><script lang=ts>に書き換える
2.import Vue from 'vue'する
3.export default {}export default Vue.extend({}) に書き換える
スクリーンショット 2020-01-24 18.28.51.png
4.componentsはそのまま
5.dataは全部を内包するオブジェクトの型を与える
スクリーンショット 2020-01-24 18.30.56.png
6.propsはObjectがなければそのまま(type指定は必要)
Objectの場合は type: Object as PropType<{ObjectType}> で型を付ける
7.methods, watch, computed は適宜引数や戻り値に型を付ける
スクリーンショット 2020-01-24 18.35.20.png

以上!おしまい。

Vue.extend()で書いたコードはこちら。
vue-ts-test/Home.vue at master · fruitriin/vue-ts-test
vue-ts-test/MyButton.vue at master · fruitriin/vue-ts-test
vue-ts-test/ResetButton.vue at master · fruitriin/vue-ts-test

Vue.extend() ポイント

  • Vue.js v2.4から本体に追加された機能
  • 従来の書き方にちょっと書き加えるだけでTypeScript化できちゃう
  • props の型の付け方以外は本当に素直に書いて型がつけられるはず
    • この辺よくわかってないので教えて下さい
  • 前述のClass Styleと混在させても問題ないはず
    • vue-property-decoratorがプロジェクトに入っていないなら、これをインストール必要はある
  • 資料を探しにくいかもしれない

Composition API (RFC)

Vue.js v3.xに取り込まれる予定のRFCです。
yarn add @vue/composition-apiすると2.xのプロジェクトでも試すことができます。

下準備としてmain.tsにVue.use()で注入する必要があります。

import VueCompositionApi from from '@vue/composition-api';
Vue.use(VueCompositionApi);

1.<script><script lang=ts>に書き換える
2.import {createComponent} from '@vue/composition-api'する
3.export default()export default createComponent({}) に書き換え
4.componentsはそのまま
5.setup()を生やす

<script lang="ts">
import { createComponent} from "@vue/composition-api";

// @ is an alias to /src
import MyButton from "@/components/MyButton.vue";
import ResetButton from "@/components/ResetButton.vue";

export default createComponent({
  setup() {
    return {};
  },
  components: {
    MyButton,
    ResetButton
  }
});

6.data()をreactive()にする。reactive()メソッドの返り値をsetup()のreturnに含める

data(){
  return {
    greatText: "Hello",
    count: 0
  }
}

// importするものにreactiveを追加する
import {createComponent, reactive} from '@vue/composition-api'

// setup()だけ抜き出し
setup(){
  const state = reactive({
    greatText: "Hello",
    count: 0    
  })
  return {
    state
  }
}

このとき、reactive()したものはdata配下のオブジェクトとして反映されているので、templateも修正する

<template>
  <div>
   <p>{{state.greatText}}</p>
   <p>{{state.count}}</p>
  </div>
</template>

8.propsはsetup関数の第一引数に渡される
9.emitはsetup関数の第二引数のcontextの中にある
10.methodsはsetup関数の中で定義してreturnするオブジェクトに含める

  setup(props, context) {
    let count = 0;
    const onClick = () => {
      alert(props.great);
      count++;
      context.emit("click", count);
    };

    return {
      onClick
    };
  }

11.computedはcomputed関数でWrapします(第一引数にコールバック)
Note: computed関数はimportが必要です
12.watchはwatch関数にWrapします(第一引数に監視対象、第二引数にコールバック)
Note: watch関数はimportが必要です
Note: watch関数は何度setup関数内で呼んでもよいし、setup関数内でreturnする必要もない

  setup() {
    const state = reactive({
      count: 0
    });
    const isRegulars = computed(() => {
      return state.count >= 3;
    });
    watch(
      () => state.count,
      () => {
        if (state.count === 3) {
          alert("常連になりました");
        }
      }
    );
    return {
      state,
      onMyButtonClicked,
      isRegulars
    };

Composition APIで書いたコードはこちら
- vue-ts-test/Home.vue at master · fruitriin/vue-ts-test
- vue-ts-test/MyButton.vue at master · fruitriin/vue-ts-test
- vue-ts-test/ResetButton.vue at master · fruitriin/vue-ts-test

Composition APIのポイント

  • Vue3.xからVueコアに導入されるAPIです
    • 2.xでは別のライブラリを導入しないと使えません
  • すべてのコンポーネントをCompotision APIで書く必要はありません
    • なんだか難しそう……と思った人は使わなくても大丈夫だし。
  • コードの変更点自体はおおきいかも
  • thisを使わないので型安全に書きやすくなります
  • コードの組織化に役立ちます
    • 複数の機能を併せ持つコンポーネントを、機能ごとに分割して定義することができます

まとめ

[あなた/プロジェクトチーム]にとって最適な方法を選ぶとよいですね!
その一助となれば幸いです。

比較してみたけど「特に好みとかないよ」「よくわかんない」って人は個人的にはVue.extend()がいいんじゃないかなあ。

studist
「伝えることを、もっと簡単に」をミッションにビジュアルSOPマネジメントプラットフォームのBtoB SaaS「Teachme Biz」を開発・運営するスタートアップ
https://medium.com/studist-dev
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした