Vue3.xのCompositionAPIとTypeScriptの書き方

2020-02-06

そろそろVue3.xが出るかもなので、目玉機能のCompositionAPIを試してみてまとめてみる。

TypeScript

Vue3.xxでは、TypeScript対応!!

やったー🎉🎉🎉🎉

composition api is 何?

composition api

ドキュメントは以下 https://vue-composition-api-rfc.netlify.com/

今までのVue2だと

  • 肥大化していくと可読性が悪い
  • コンポーネントのロジックの再利用性がつらみ
  • TypeScript書きづらい。
  • テスト書きにくい

みたいなことがあった。

これをReact hooksをヒントに新たにAPIを作成したものがcomposition api。

TypeScript対応だと現状vue-property-decoratorでデコレータ使うか、vue.extendの2択しかないが、これだとアノテーション(型推論)の恩恵を受けづらいという問題もあった。

vue.extendを使う場合

TypeScript のサポートの通りだが、importをVueから行いExtendVueオブジェクトを返すメソッドをexportすれば使用可能。(もちろんlang=“ts”もする。)

基本的にcomponents以外のライフサイクルフックに型を定義していく。

// JavaScript
data() {
  retrun {
    text: 'text',
    price: 120
  }
}

// TypeScript 
// 最初に型を作る
export type DataItem = {
    text: String
    price: Number
}

// 
data(): DataItem {
  retrun {
    text: 'text',
    price: 120
  }
}

methods,computedなどはそれぞれの関数に型をつけていく ※公式ドキュメント通り

methods: {
  greet (): string {
    return this.msg + ' world'
  }
},
computed: {
  greeting(): string {
    return this.greet() + '!'
  }
}

導入のハードルがもっとも低いが細かい所まで型推論できなそう。

デコレータを使うやり方

JavaScriptのclassを用いたクラスベースの書き方。

vue-property-decoratorで必要なものをimportする。

使わない場合も一応書けるが、propsなどがちょっと見にくい感じになるので導入している所が多い。

import Vue from 'vue'
import {型指定したいもの Component, Vueなど} from 'vue-property-decorator'

componentsは、@Component({})で囲う。

@Component({
  AddButton
})

componentsがない場合は@Componentと書けばOK

その他は、export default class {{Name}} extends Vue {}と記述。それぞれの処理を書いていく。 この時点で、だいぶシンタックスが変わるが以下のように記述していく。

// data() リアクティブになる。
message: string = 'message';
price: Number = 1230

// propsは@Propを使用する。複数の場合は都度使っていく

// JS
props: {
  text: {
    type: String,
    default: ""
  }
}

//TS
@Prop({ default: "" }) text!: string

watch, computed, methods

サンプルコード書かないが以下の様な形

  • watchは@Watchとしてデコレータする
  • computedはクラス構文のgetterメソッドで定義する。
  • methodsはそのままクラス構文の中で使用可能。

※Vue3のRFCによると非推奨の書き方になるようで、今からプロジェクト始める場合は導入しないほうがよさそう。

composition api

目玉機能!

main.tsで@vue/composition-apiをimportする。

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

各Vueコンポーネントで使う時

dataやMethodsは、setup関数内でリアクティブにする。

※importは、必要なものを適宜変更する

import {
  createComponent,
  reactive,
  SetupContext
} from '@vue/composition-api'

export default createComponent({
  setup() {
    // リアクティブデータ、関数を定義していく

    const state =reactive({
      text: 'text',
      price: 1200
    }),

    const isNumber = (price: number) => {
      state.price = price
    },

    // 最後にreturnで返す
   return {
      state,
      isNumber
    }
  }
})

propsの定義はtype Propsを定義してsetup関数の引数としてPropsを渡してアノテーションをつける

type Props = {
  text: string;
};

export default createComponent({
  props: {
    text: {
      type: String,
      default: "default"
    }
  },
  setup(props: Props) {
    props.text
  }
})

算出プロパティはsetup関数内で、以下のように記述。setup関数内でretrunする。

const priceLength = computed(() => {
  return state.price.length
})

感想

  • 関数をretrunで返すシンタックスの方が可読性は良さそう
  • 今までthisを書いていた箇所は不要になる。
  • refなのかリアクティブなのか一瞬わからなくなる

TODO

  • 他のVue3.xxで追加される機能についても試す

ソースコードはこちらのリポジトリにあります。

Google Analyticsを使っています。