ビザスクlite事業部フロントエンドエンジニアの小柳(@mascii_k)です。
弊社ではモダンなフロントエンド開発手法にシフトしつつあり、Figma で構築したデザインシステム上でデザインし、それに対応するものを Vue.js 2.x 系で実装する開発がスタンダードとなっております。
現在 Vue.js 3.0.0 の正式リリースが間近とされていて、弊社としても積極的にマイグレーションをしていきたいと思っております。
今回は Vue 2.x 系向けに作られた UI コンポーネントの Vue 3.0 系へのマイグレーションに向けた検証結果を公開します。
弊社の UI コンポーネント事情
弊社では Vuetify や Element UI といったコンポーネントフレームワークには依存せず、極力スクラッチで UI コンポーネントを作って開発しています。

しかし、カレンダーから日付を選択するコンポーネントは複雑なため、例外的に vuejs-datepicker
(npm) を活用しています。

検証
弊社で内製している UI コンポーネント群は単純なものが多く、Vue 3.0 系へ容易にマイグレーションできると考えています。
そのため、適度な複雑さがあり弊社でも活用している vuejs-datepicker
を Vue 3.0 系へマイグレーションする検証をしてみることにしました。
検証に用いた環境は Vue CLI で作成しました。環境構築の手順は私が Qiita にて公開している Vue 3.0.0-betaのお試し環境をVue CLIで作ってみた を参照ください。
vue ファイルからビルドし直しになった
通常は import Datepicker from 'vuejs-datepicker';
のようにしてビルド済みのファイルを import しますが、Vue 3.0.0 beta ではブラウザでの実行時にエラーが出てしまいました。
このエラーは vuejs-datepicker
が vue-template-compiler
の 2.6 系を用いてビルドされているので、 Vue 3.0 系と互換性がないため発生したと思われます。
そのため import Datepicker from 'vuejs-datepicker/src/components/Datepicker.vue';
のようにしてビルド前の vue ファイルを import するように変更しました。
変更後、vuejs-datepicker
側で利用している Stylus の導入が必要となりました(なお、弊社では Sass を採用しています)。
prop のデフォルト値が反映されない問題が発生
import を変更することでいったんビルドは通るようになりました。
しかし、 PickerDay.vue
というコンポーネントにおいてブラウザでの実行時にエラーが出てしまいました。
エラーを追っていくと PickerDay.vue
の dayCellContent
という prop 周りで問題が起きていました。
// PickerDay.vue
export default {
props: {
dayCellContent: {
type: Function,
default: day => day.date // <- ここのデフォルト値が効いてないらしい
},
}
}
親コンポーネントである Datepicker.vue
にも dayCellContent
という prop があって、これをそのまま PickerDay.vue
側に渡しているようでした。Datepicker.vue
側にデフォルト値の設定がなかったため、エラーが出たものと思われます。
対応方法は2通りありました:
- 対応1:
Datepicker.vue
の propdayCellContent
にデフォルト値(day => day.date
)を設定する - 対応2:
<Datepicker>
に:dayCellContent="day => day.date"
を設定する
<!-- 対応2の例; App.vue -->
<template>
<Datepicker :dayCellContent="day => day.date" />
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import Datepicker from 'vuejs-datepicker/src/components/Datepicker.vue';
export default defineComponent({
name: 'App',
components: {
Datepicker,
},
});
</script>
カスタムコンポーネントの v-model の仕様変更
prop の問題は解決できましたが、今度は <Datepicker>
で v-model を付けても値が反映されない現象が発生しました。
<!-- App.vue -->
<template>
<Datepicker v-model="date" :dayCellContent="day => day.date" />
</template>
この現象がきっかけで、カスタムコンポーネントにおける v-model の仕様が変更となっていたことに気付きました。
(RFC: https://github.com/vuejs/rfcs/blob/master/active-rfcs/0011-v-model-api-change.md)
対応方法は2通りありました:
- 対応1: 利用側で
v-model
->v-model:value
とし、Datepicker.vue
側でinput
ではなくupdate:value
を emit するように修正する - 対応2:
v-model="date"
をやめて:value="date"
と@input="val => date = val"
に分解する
以上で vuejs-datepicker
を Vue 3.0.0 beta で利用することが可能となりました。
まとめ
今回の検証で発生した prop の問題以外は事前に予測可能なもので、Vue 3.0 系へのマイグレーションに必要な変更はそれほど多くない印象でした。
また、この検証がきっかけでカスタムコンポーネントにおける v-model の仕様が変更があることに気付けて良かったです。
結論、外部で公開されている UI コンポーネントへの依存が少ないほど、 Vue 3.0 系へのマイグレーションは容易になるのではないかと思いました。
(この記事を執筆中、Vue.js コアチームメンバーのkazuponさんもほぼ同じ結論をつぶやいていることに気づきました)
一緒に働くエンジニアを募集中!
ビザスクに少しでも興味のあるWebエンジニアの方がいたら、ぜひお話を聞かせてください!詳しい募集要項は下記リンクからアクセスしてください。
- エンジニア採用ページ: https://visasq.co.jp/engineer-recruitment
- ビザスクの中の様子はこちらから >> https://square.visasq.com/