最近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する
3.export default
をexport default class {Class名} extends Vue
に書き換える
4.classのすぐ上に@Component
デコレータを付ける
5.子コンポーネントがある場合は@Component()
デコレータの中に移動する
6.propsは@Prop
デコレータ付きのプロパティとして定義する
7.$emitは@Emit()デコレータ付きのメソッドにする
イベントの送出用に別のメソッドに分ける
9.watchは@Watch()デコレータ付きのメソッドにする
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({})
に書き換える
4.componentsはそのまま
5.dataは全部を内包するオブジェクトの型を与える
6.propsはObjectがなければそのまま(type指定は必要)
Objectの場合は type: Object as PropType<{ObjectType}>
で型を付ける
7.methods, watch, computed は適宜引数や戻り値に型を付ける
以上!おしまい。
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()がいいんじゃないかなあ。