1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【備忘録】Nuxt.js + Composition API でVue3 + Vuex4のように書く

Last updated at Posted at 2021-07-02

はじめに

会社でとある業務管理システムを開発していて、最近Vue2→Vue3に書き換えました。
しかしながら、だいぶ複雑な構造になりそうだったので、Nuxt.jsに乗せようと思い着手しました。
NuxtでもVue3 + Vuex4のまま書きたかったのですが、意外に試行錯誤したので、ここに備忘録として残します。

本記事で触れる事

Vue3とVuex4の基本的な記述を、Nuxt.js + Composition APIを使用して再現する
※Nuxt.jsの環境構築等は省略します。詳細は公式を参照してください。

開発環境

移行前(Vue3)の環境

Package.json
"dependencies": {
	"balm-ui": "^9.29.1",
	"moment": "^2.29.1",
	"theme": "^0.1.0",
	"typescript": "^4.3.2",
	"uikit": "^3.6.21",
	"vue": "^3.0.11",
	"vue-router": "^4.0.8",
	"vuex": "^4.0.0",
	"vuex-persistedstate": "^4.0.0-beta.1"
},
"devDependencies": {
	"@parcel/transformer-typescript-tsc": "^2.0.0-beta.3.1",
	"@parcel/transformer-vue": "2.0.0-beta.2",
	"@parcel/validator-typescript": "^2.0.0-beta.3.1",
	"@types/uikit": "^3.3.1",
	"parcel": "^2.0.0-beta.2",
	"sass": "^1.32.13"
},

移行後(Nuxt2)の環境

Package.json
"dependencies": {
	"@nuxtjs/axios": "^5.13.6",
	"@nuxtjs/composition-api": "^0.24.5",
	"@nuxtjs/dotenv": "^1.4.1",
	"balm-ui": "^8.40.4",
	"core-js": "^3.15.1",
	"moment": "^2.29.1",
	"nuxt": "^2.15.7",
	"theme": "^0.1.0"
},
"devDependencies": {
	"@nuxt/types": "^2.15.7",
	"@nuxt/typescript-build": "^2.1.0",
	"@types/uikit": "^3.3.1",
	"fibers": "^5.0.0",
	"nuxt-svg-loader": "^1.2.0",
	"sass": "^1.35.1",
	"sass-loader": "10.1.1",
	"uikit": "^3.6.22"
}

※開発途中なので、まだ増えたり減ったりする予定です。

プロジェクト内ディレクトリ構造

ほとんどデフォルトのままです。※のところが解説で使用するファイルです。

├── assets
├── components
├── layouts
├── plugin
├── types
├── utils
├── pages
│   └── index.vue ※
├── store
│   ├── module1.ts ※
│   └── module2.ts ※
├── package.json
├── tsconfig.json
├── nuxt.config.ts
└── yarn.lock

@nuxtjs/composition-apiを使ってVue3 + Vuex4のように書く

Nuxtプロジェクトに@nuxtjs/composition-apiを追加します。
ちなみにnuxtjs/composition-apiの公式は こちら です。

Vuex4で書いたStoreを少し書き直す

createStore@nuxtjs/composition-apiやNuxtのvuexにはなかったので、
試行錯誤しましたが、結局以下の書き方に落ち着きました。module2.tsも同じように書きました。

store/module1.ts
import { InjectionKey, useStore as baseUseStore } from "@nuxtjs/composition-api";
import { Store as VuexStore, Commit } from "vuex";

//ファイル名(module1)でまとめる
export type StoreType1 = {
    module1: StateType1
}

type StateType1 = {
    data1: string;
    data2: string;
}

export const key: InjectionKey<VuexStore<StateType1>> = Symbol();

//CreateStoreは使えない
export const state = (): StateType1 => ({
    data1: "テスト1",
    data2: "テスト2",
});

export const mutations = {
    //省略
};

export const actions = {
    setTestAction({ commit }: { commit: Commit }, payload: string) {
        //Mutation.SET_TEST_ACTION は別ファイルにて定数で名前を定義
        commit(Mutation.SET_TEST_ACTION, payload);
    },
};

//useStoreをエクスポート
export const useStore = () => {
	return baseUseStore(key);
};

storeをインポートする

index.vue内は以下のようにしました。

pages/index.vue
<template>省略</template>
<script lang="ts">
    //useStoreはVue3ではvuexからインポートしていたが、composition-apiからインポートする
    import { defineComponent, reactive, useStore } from "@nuxtjs/composition-api";
    //store内stateのtypeをインポート
    import { StoreType1 } from "~/store/module1.ts"
    import { StoreType2 } from "~/store/module2.ts"
    
    //Vue3のcomposition APIと変わらない
    export default defineComponent({
        setup() {
            const data = reactive({
                aaa: "",
                bbb: "",
            });
            //storeをインスタンス化
            const store = useStore<StoreType1 & StoreType2>();
            //console.log(store) => storeのモジュールがまとまって取得されている

            //stateを試しに参照 - gettersも普通に使えると思われる
            const m1 = store.state.module1;
            const m2 = store.state.module2;
            console.log(m1.data1) //=> テスト1
            console.log(m1.data2) //=> テスト2

            //値をセット
            const setDatas = async () => {
                //[モジュール名(ファイル名)]/[actionsで設定した名前]
                await store.dispatch("module1/setTestAction", "test")
            }
            
            //以下省略

            return { data };
        },
    });
</script>
<style lang="scss" scoped>
    //省略
</style>

最後に

せっかくVue3の書き方に慣れたところで、そのままの記述で移行できないかと試行錯誤しました。
いろいろ調べたのですが、情報を探すのになかなか苦労したので記事にしました。
まだまだ改善すべき点はあるとは思いますが、まずは記録として。

その他参考記事

NuxtをTypeScript化する際に参考にさせて頂きました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?