Vue3でもClass Style Componentが使えそう
Vue2時代にTypeScriptを使う場合は Vue Property Decolator(Vue Class Component)か,Vue.extendでした.
正式リリースからもうすぐで1年経つVue3ではTypeScriptとの親和性が向上し,Class Componentの必要性は薄れてしまいました.しかし,どうやらVue3でもClass Style Componentが使えそうなので試してみました.
Vue CLIでプロジェクト作成
$ vue create sample
Vue CLI v5.0.4
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Router, Vuex, CSS
Pre-processors, Linter
? Choose a version of Vue.js that you want to start the project with 3.x
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected
polyfills, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback
in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported
by default): Sass/SCSS (with dart-sass)
? Pick a linter / formatter config: Prettier
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated
config files
? Save this as a preset for future projects? No
注目すべきは,Vue2のときと同様に「Use class-style component syntax?」という質問が表示されることです.こちらを yes にしてプロジェクトを作成し,プロジェクト内のpackage.jsonを見てみると
"vue-class-component": "^8.0.0-0"
となっていて,Class Component v8のRC版が使われているようでした.
ただし,Property Decoratorはインストールされておらず,Class Componentのみでした.vue2のときはProperty Decoratorも一緒にインストールされていた気がするので,Property DecoratorはVue3では使えないのかなと邪推したくなります.
SFCの中を見てみる
Vue3のClass ComponentはVue2と同じ書き方になっているのでしょうか? 自動生成された .vueファイルの中身を覗いてみます .
<script lang="ts">
import { Options, Vue } from "vue-class-component";
import HelloWorld from "@/components/HelloWorld.vue";
@Options({
components: {
HelloWorld,
},
})
export default class HomeView extends Vue {}
</script>
Vue2では @Component としていた箇所が @Options に変わっていました.
とりあえずサンプル状はデコレーターの名前が変わった以外に目立った違いはわかりませんでした.
とりあえず,Class Componentで書かれたVue2プロジェクトを移行する際に全部 Composition APIに書き直すみたいな芸当をしなくて済みそうで,淡い期待を抱いてしまいます.
ただ,ここまで来たら Property Decolatorもそのまま移行できないかなと思ってしまいます.
Property Decolatorを入る
"vue-property-decorator": "^9.1.2",
とりあえず Property Decoratorの最新版を入れてみます.Property DecoratorでSFCを書き直してみると,ワーニングは出ますがとりあえず動きました…
warning in ./node_modules/vue-property-decorator/lib/index.js
export 'default' (reexported as 'Component') was not found in 'vue-class-component' (possible exports: Options, Vue, createDecorator, mixins, prop, setup)
warning in ./node_modules/vue-property-decorator/lib/index.js
export 'default' (reexported as 'Vue') was not found in 'vue' (possible exports: BaseTransition, Comment, EffectScope, Fragment, KeepAlive, ReactiveEffect, Static, Suspense, Teleport, Text, Transition, TransitionGroup, VueElement, callWithAsyncErrorHandling, callWithErrorHandling, camelize, capitalize, cloneVNode, compatUtils, compile, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, createHydrationRenderer, createPropsRestProxy, createRenderer, createSSRApp, createSlots, createStaticVNode, createTextVNode, createVNode, customRef, defineAsyncComponent, defineComponent, defineCustomElement, defineEmits, defineExpose, defineProps, defineSSRCustomElement, devtools, effect, effectScope, getCurrentInstance, getCurrentScope, getTransitionRawChildren, guardReactiveProps, h, handleError, hydrate, initCustomFormatter, initDirectivesForSSR, inject, isMemoSame, isProxy, isReactive, isReadonly, isRef, isRuntimeOnly, isShallow, isVNode, markRaw, mergeDefaults, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, openBlock, popScopeId, provide, proxyRefs, pushScopeId, queuePostFlushCb, reactive, readonly, ref, registerRuntimeCompiler, render, renderList, renderSlot, resolveComponent, resolveDirective, resolveDynamicComponent, resolveFilter, resolveTransitionHooks, setBlockTracking, setDevtoolsHook, setTransitionHooks, shallowReactive, shallowReadonly, shallowRef, ssrContextKey, ssrUtils, stop, toDisplayString, toHandlerKey, toHandlers, toRaw, toRef, toRefs, transformVNodeArgs, triggerRef, unref, useAttrs, useCssModule, useCssVars, useSSRContext, useSlots, useTransitionState, vModelCheckbox, vModelDynamic, vModelRadio, vModelSelect, vModelText, vShow, version, warn, watch, watchEffect, watchPostEffect, watchSyncEffect, withAsyncContext, withCtx, withDefaults, withDirectives, withKeys, withMemo, withModifiers, withScopeId)
おそらくこれは,Component -> Options になったことによるものです.
続いて Property Decorator v10のRC版を入れてみます.
"vue-property-decorator": "^10.0.0-rc.3",
以下のようにSFCを書き直してみると,特にワーニングが出ることもなく動きました.
<script lang="ts">
import { Prop, Options, Vue } from "vue-property-decorator";
@Options({})
export default class HelloWorld extends Vue {
@Prop({ type: String, required: true })
msg!: string;
}
</script>
まとめ
RC版ではありますが,Vue3でもProperty Decoratorが使えることがわかりました.今回は検証のためにClass Style Componentを選択しましたが,今から新規にプロジェクトを作成する場合はこちらは選ばないほうが良いです.
しかし,既存のVue2プロジェクトをVue3に移行するハードルが少し下がった気がしました.とりあえず,Property Decoratorのまま移行して徐々にComposition APIに書き換えるという戦略も選べるので,全部を一気に書き換えるよりは現実的なプランを選べそうです.今回は @vue/compat modeの検証まではできていないので,引き続き調べる必要がありそうです.