Vue2からVue3への変化と慣れていくためのTips
モチベーション
- Vue2系サポート終了(23年末予定)を踏まえて、今後はVue3に触れる機会が増えそう
- 現在Vue2を使っているけどVue3へリファクタする予定があり、慣れていく必要が出てきた
記事の内容
- Vue3を取り巻く環境とかエコシステムなど整理
- Vue3に慣れる為に知っておくべきことを整理
- 移行に伴う破壊的変更の内容などは記載してない
- ある程度Vue2を触った事があるのを前提で書いてる部分が多いです
なぜVue3に慣れる必要があるのか
1. Vue2のサポート終了
Vueの公式によるとVue2系が2023年の末に終了されることが告知されています。
Vue2系は2022年6月にリリースされた2.7系が最後で、今後は新しい機能などは追加されず、セキュリティ対応など最低限のアップデートのみの対応となります。
それに伴ってVue2からVue3へリファクタ等の対応する必要があります。
2. Vue2とVue3の書き方が大きく異なる
Vueではバージョンや環境によって書き方が大きく変わっています。
まず、Vue2ではOptions APIという書き方が主流でした。
<script>
export default Vue.extend({
name: "App",
components: {
},
data() {
return {
};
},
methods: {
},
watch: {
},
});
</script>
Vue.extend
の中にcomponents
やmethods
毎に処理を記述する方法で、Vueでネット検索するとよく見る書き方です。
この書き方はVue3でも互換性があるのですが、Vue3での主流な書き方ではないです。
さらにOptions APIのもう一つの書き方で、クラスコンポーネントという書き方もあります。
<script lang="ts">
import Component from "vue-class-component";
import Vue from "vue-property-decorator";
@Component
export default class extends Vue {}
</script>
クラス構文を利用する書き方です。Vue.jsでTypeScriptを導入している場合によく見る書き方です。
一方、Vue3ではComposition APIが主流となっています。
<script setup lang="ts">
import {ref} from "vue";
const exampleNo = ref(100) // Options APIのdataに該当
// Options APIのmethodsに該当
const addExampleNo = (): void => exampleNo++
// Options APIのcomputedに該当
const hogehoge = computed(
(): number => {
return exampleNo * 2
}
)
</script>
Composition APIではスクリプトタグの中でsetup
を記述する上記の書き方が主流です。
しかし、Vue3.2系以前はsetup()関数を使った下記の様な書き方も見かけます。
<script lang="ts">
import { defineComponent, ref, } from "vue";
export default defineComponent({
name: "App",
setup() {
const exampleNo = ref(100) // Options APIのdataに該当
// Options APIのmethodsに該当
const addExampleNo = (): void => exampleNo++
// Options APIのcomputedに該当
const hogehoge = computed(
(): number => {
return exampleNo * 2
}
);
return { exampleNo, addExampleNo, hogehoge }
}
})
</script>
setup()関数を使う場合だと<script lang="ts">
の部分にsetup属性が付与されていません。
Vue3では上記の書き方を見かけることもありますが、コードの記述量も多くなりがちで、Vue3.2系以降では<script setup lang="ts">
のようにスクリプトブロックにsetup属性を付与して書くのが主流です。
気をつけないといけない事は、Vueで調べ物をするときや教材でソースコードを見るときに、どの書き方で書かれているのかを最初に確認する事です。上記の書き方について、ざっくりと知っているだけでも理解が進みます。
この記事ではComposition API(3.2〜)での書き方で示していきます。
Vue3のエコシステム
以下の表はVue2とVue3で利用する主なライブラリ等の一覧です。
Vue2 | Vue3 | 主な用途 | |
---|---|---|---|
バンドルツール | VueCLI | create-vue | 実行のためのファイル変換 |
コード補完 | Vuter | Volar | Vueコードの補完 |
ルーティング | Vue Router 3 | Vue Router 4 | SPAの作成 |
状態管理 | Vuex | Pinia | コンポーネント間のデータを管理する |
UIライブラリ | Vuetify2 | Vuetify3 | UIの提供 |
(*vue3に記載しているエコシステムもvue2系で使えるものもあります)
上記の表からエコシステムはVue2から多くのものが置き換えられているのが分かります。
更に、これらは正式版としてVue3に対応するようになりました(2022年11月時点)
VueはTypeScriptと相性が悪いと言われていましたが、Vue3自体がTypeScriptで一新されたのと、付随するエコシステムもTypeScriptに準拠しているため、TypeScript絡みで悩まされる事はほぼ無くなった印象です。
また、Vue自体の話にはなるのですが、個人的にVue3のsetup関数に慣れなかった部分がありました。
ところが、Vue3.2から使えるsetupをスクリプトタグ内で記述できるようになった事でコード量も減り、見通しもよくなった事でかなり書きやすくなりました。
世間ではReactが優勢な空気がありますが、Vue3も検討に上がるレベルで安定した段階になっていると個人的には思います。
Vue3を使ってみる
新規プロジェクトの作成
Vue3でプロジェクトを新規で作成する時はcreate-vue
を使います。
create-vueはVue公式のプロジェクトを作成するためのライブラリです。
今までVueのプロジェクトを作成するときはvue CLI
を利用していたのですが、create-vueが登場したことにより、vue CLIはメンテナンスモードになりました。
作成するときはコマンドラインから
npm init vue@latest
を入力します。
TypeScriptやPiniaはYesを選択します。
インストールが完了したら、以下のコマンドを入力してプロジェクトを立ち上げます。
cd vue3-example-app
npm install
npm run dev
create-vueではViteが使われている
create-vueでVueプロジェクトを作成すると、バンドルツールとして自動的にViteが利用されます。
vue CLIではWebpackを利用して各ファイルのバンドルを行い、ブラウザで実行可能なファイルに変換を行なっていましたが、実行速度が課題となっていました。
この速度を解決するために、create-vueは従来のWebpackからViteへバンドルツールの変更が行われています。
Viteではコード変更を行った際も反映の速さを実感できるくらい違うので、納得できます
(VScodeを使っている場合)拡張機能をインストール
vue3のコーディング用に使われる拡張機能でVolorをインストールします。
過去vue2を使っている場合はVuterが既にインストールされている可能性があるので、インストール済みからVuterがないか探します。
もしある場合は、無効にする(ワークスペース)を選択して、Vuterを利用を使わないようにします。
以上でVue3が記述できるようになりました。
Vuetify3
VueのUIライブラリであるvuetifyもつい最近(2022年11月)バージョン3系がリリースされました。
せっかくなので、vuetify3もインストールしてみます。
すでにVueのプロジェクトは作成しているので、Manual stepsに沿ってVuetify3を追加します。
インストールと設定が完了したらv-btn
など気になるコンポーネントを表示してみましょう
VueRouter4
vueRouterを使う事で画面遷移(いわゆるSPA)を簡単に行うことができます。
プロジェクト作成時にVueRouterを追加しているため、コードを追加するだけです。
- router.tsにsampleへのルーティングを追加
- 対応するコンポーネントを作成
これでルーティングを行うことができます。
- View
<template>
<div>
<h1>Vue3の練習</h1>
</div>
</template>
- Component
<script setup lang="ts">
</script>
<template>
<v-container>
<v-row>
<v-col cols="12">
<v-btn>Vuetifyで記述</v-btn>
</v-col>
</v-row>
</v-container>
</template>
router.tsにsampleへのルーティングを追加します。
import { createRouter, createWebHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
// 省略、以下追加する
{
path: "/sample",
name: "sample",
component: () => import("../views/SampleView.vue"),
},
],
});
export default router;
最後にApp.vueにsampleへ移動するリンクを追加します。
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
<RouterLink to="/sample">Sample</RouterLink> // 追加
</nav>
Pinia
PiniaはVueの公式ライブラリである状態管理ライブラリです。
以前の状態管理ライブラリであったVuexと似ていますが、PiniaではTypeScriptをサポート、mutation
を廃止し、値を更新する際もcommit
ではなくactions
から呼び出す形になり、Composition APIで記述しているのと変わらない感覚で状態管理を記述できるようになりました。
Piniaではstore
ファイル内にtsファイルを作成しdefineStore
をインポートし記述します。
import { defineStore } from "pinia";
export const useCounterStore = defineStore({
state: () => {
// データの本体
},
getters: {
// データの加工処理
},
actions: {
// データの変更処理
}
})
上記の例のように、データそのものはstate
で管理します。
state
に保存されたデータに対して、getters
にてデータの加工処理も行えます。
また例ではuseCounterStore
だけを定義していますが、tsファイル内で複数定義する事も可能です。
Vue3で抑えておきたいこと
Vue3においてよく使う書き方で、Vue2と大きく変わった部分をまとめました。
Vue3の変更点はたくさんありますが、初見でも混乱しないようによく使う書き方に絞ってまとめています。
ref,reactive
Vue3ではリアクティブな値(vue2でいうdata)はref
とreactive
を使います。
Vue2からの初見ではconst
に続けて書いていたりしているので違和感を持ちますが、慣れるとすぐリアクティブな値であると分かります。
<script setup lang="ts">
import { ref } from "vue";
const hogehoge:number = ref(0)
</script>
<template>
<div>{{ hogehoge }}</div>
</template>
オブジェクトの場合はreactive
が使われることが多いです。
<script setup lang="ts">
import { reactive } from "vue";
const hogehoge = reactive({ title: "" , name: "" });
</script>
<template>
<div>{{ hogehoge }}</div>
</template>
コンポーネントの呼び込み
vue3では別コンポーネントをインポートするとき、components
にコンポーネント名を記述する必要がなくなりました。
<script setup lang="ts">
import SampleComponent from ./SampleComponent.vue;
</script>
<template>
<SampleComponent />
</template>
記述量が減り、import
だけで済むので分かりやすく明確になりました。
watchEffect()
- watchEffectはVue3から登場した新しい記法です。watchと似ていますが、監視対象を指定しません。refやreactiveでリアクティブにした変数のどれかが変更したときに実行をしてくれます。
<script setup lang="ts">
import { watchEffect, ref } from "vue";
const count = ref(0);
const addCount = () => count.value++;
watchEffect(() => console.log(`クリックした回数:${count.value}`));
</script>
<template>
<v-container>
<v-row>
<v-col cols="12">
<v-btn @click="addCount">数字を増やす</v-btn>
</v-col>
</v-row>
</v-container>
</template>
ライフサイクルフック
ライフサイクルフックでは読み込み時やレンダリング時などに処理を実行する関数です。
<script>
export default {
created() {
console.log('createdが実行されました')
}
}
</script>
特筆すべきなのは、Vueアプリケーションの初期化処理後に実行するbeforeCreate
とcrated
を明示する必要が無くなった所です。
これはComposition APIでは<script setup>
内に記述したものについては全てbeforeCreate
〜crated
間で実行されるため、わざわざ呼び出す必要が無くなったためです。
また、その他のライフサイクルでは明示的に書く必要がありますが、微妙に書き方が変わっているので注意が必要です。
Vuu2(Options API) | Vue3(Composition API) |
---|---|
beforeCreate | - |
created | - |
beforeMount | onBeforeMount() |
mounted | onMounted() |
beforeUpdate | onBeforeUpdate() |
updated | onUpdated() |
beforeDestroy | onBeforeMounted() |
destroyed | onUnmounted() |
Composition APIでは接頭にon
をつけています。なおdestroyed
に限ってはon
を付けずにonUnmounted
としています。
最後に
Vue3ではエコシステム含め開発しやすい環境が整ってきました。
今後はVue3を書く機会も増えてくるはずなので慣れていきたいです。
Discussion