はじめに
- Vue3.0で既存のライブラリを扱う場合にどう考えればいいかという話
- VuexやVue Routerが公式にComposition APIを対応するまでの話
setup関数でVuexにアクセスする
とりあえずサンプルです。
<script lang="ts">
import { createComponent, onBeforeMount } from '@vue/composition-api'
import { fetchActionName } from '@/store/actions'
export default createComponent({
setup(props, context) {
const store = context.root.$store
onBeforeMount(async () => {
await store.dispatch(fetchActionName)
})
return { state: store.state }
}
})
</script>
setup関数のcontextの中にはrootというオブジェクトがあります。型定義をみるとVueのインスタンスがそのまま入っていています。
export declare type ComponentInstance = InstanceType<VueConstructor>
昔からVuexなどでは this.$store
といった形でインスタンスに生やすライブラリがありますが、そのあたりのライブラリは一旦この方法で対処できると思われます。
データの表示はsetupの返り値でVuexのstateを返すことでhtml上で表示することができました。しかし、表示を加工して返したい場合などが大半だと思うので素直にcomputedを定義した方が良いのかもなと感じています。この辺は公式が対応するまで辛そう。
APIデータ取得などのactionsは新しいライフサイクルメソッド上で扱う必要が出てきますが、基本はcreated、mounted、destroyedの範囲で実装していれば移行は問題はないと思います。
modulesを使っている場合などでアクション名が複雑化している場合や、dispatchのタイプミスが怖い人なんかはactionsの関数名をmutationsのようにVuexのファイルに近い場所に配置にして別途importしていくのが良いと思います。payloadの型定義はゆるふわになりますがそこは送る手前でオブジェクトに型定義しておけば良いと思います。
setup関数でVue Routerにアクセスする
Vue Routerも同様の方法で取ってくることができます。
<script lang="ts">
import { createComponent } from '@vue/composition-api'
export default createComponent({
setup(props, context) {
const router = context.root.$router
function move() {
router.push({ name: 'about' })
}
return { move }
}
})
</script>
Vuexの中にルーター情報を連携してたりしなければほとんど問題が無いと思います。