概要
Vue.jsでVuex+axiosを利用してみました。
コードをシンプルにすると理解が進んで良いです^^
GitHubにコードをUPしましたので、よろしければご参考ください。
https://github.com/kai-kou/vue-js-typescript-vuex-axios
環境構築
Dockerを利用して、APIのモックサービスも立ち上げられるようにdrakovを利用しています。
drakovについては下記をご参考ください。
api blueprintとdrakovを利用してAPIモックサーバを立ち上げる
https://qiita.com/kai_kou/items/bdbb6c3f8d1ac655595d
> mkdir 任意のディレクトリ
> cd 任意のディレクトリ
> vi Dockerfile
> vi docker-compose.yml
FROM node:10.8.0-stretch
RUN npm install --global @vue/cli
RUN npm install -g drakov
WORKDIR /projects
version: '3'
services:
app:
build: .
ports:
- "8080:8080"
volumes:
- ".:/projects"
tty: true
drakov:
build: .
ports:
- "3000:3000"
volumes:
- "./docs:/projects"
tty: true
command: drakov -f "**/*.md" --public --watch --p 3000
API用のmdファイルを用意しておきます。
> mkdir docs
> touch docs/sample.md
# GET /
+ Response 200 (text/plain)
Hello World!
コンテナを起動して、Vue.jsのプロジェクトを作成するコンテナに入ります。
> docker-compose up -d
> docker-compose exec app bash
> vue create app
Vue CLI v3.0.1
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Vuex, Linter, Unit
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript for auto-detected polyfills? Yes
? Pick a linter / formatter config: TSLint
? Pick additional lint features: Lint on save
? Pick a unit testing solution: Mocha
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
? Pick the package manager to use when installing dependencies: (Use arrow keys)
❯ Use Yarn
Use NPM
プロジェクトが作成されたらVue.jsサービスを起動します。
> cd app
> yarn serve
src/store.tsに実装を追加します。
Stateにcounter
とmessage
を用意してcounter
をインクリメントするアクションと、APIからテキストを取得してmessage
に保存するアクションを追加しました。
import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios';
Vue.use(Vuex);
interface State {
counter: number;
message: string;
}
export default new Vuex.Store({
state: {
counter: 0,
message: '',
} as State,
getters: {
getCounter: (state, getters) => () => {
return state.counter;
},
getMessage: (state, getters) => () => {
return state.message;
},
},
mutations: {
increment(state, payload) {
state.counter+= 1;
},
setMessage(state, payload) {
state.message = payload.message;
},
},
actions: {
incrementAction(context) {
context.commit('increment');
},
async getMessageAction(context) {
const msg = await axios.get('http://localhost:3000').then(
(res) => res.data,
() => ''
);
const payload = {
message: msg,
};
context.commit('setMessage', payload);
},
},
});
src/main.tsはそのままです。
import Vue from 'vue';
import App from './App.vue';
import store from './store';
Vue.config.productionTip = false;
new Vue({
store,
render: (h) => h(App),
}).$mount('#app');
src/App.vueでStoreが利用できるようにします。
画像をクリックとcounter
のインクリメントとAPIアクセスがされるようにしています。
<template>
<div id="app">
<p>{{ message }}</p>
<img alt="Vue logo" src="./assets/logo.png" @click="increment">
<HelloWorld :msg="`Welcome to Your Vue.js + TypeScript App ${this.counter}`"/>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from './components/HelloWorld.vue';
@Component({
components: {
HelloWorld,
},
})
export default class App extends Vue {
private get counter(): number {
return this.$store.getters.getCounter();
}
private get message(): string {
return this.$store.getters.getMessage();
}
private increment(): void {
this.$store.dispatch('incrementAction');
this.$store.dispatch('getMessageAction');
}
}
</script>
(略)
ブラウザで確認してみます。
> open http://localhost:8080/
はい。
うまくAPIにアクセスできてますね。
ポイントとしてはsrc/store.tsでAPIアクセス時にasync
とawait
を利用するところでしょうか?利用しなくても以下のように書けますが、フラット化を意識していないと、行き着く先に、きっとコールバック地獄が待っていると思います^^
getMessageAction(context) {
axios.get('http://localhost:3000').then(
(res) => res.data,
() => ''
).then(msg => {
const payload = {
message: msg,
};
context.commit('setMessage', payload);
});
},
追記(2020/04/06)
ネストを回避する手段について、@masmatsum さんからコメントを頂きました。
コメントにあるサンプルコードや記事のように、ネストを回避する手段はasync
とawait
を利用する他にもありますので、ケースに合わせた実装方法をご検討ください。
GitHubの方に、vuex-type-helperというライブラリを利用してstoreをモジュール化する実装も置いてますので、ご参考ください。
vuex-type-helperについては別記事にまとめています。
VuexをTypeScriptで利用するのに悩んだ
https://qiita.com/kai_kou/items/fdd8ecd07995571da8a1
それでは、良きVuex+axiosを利用したVue.js開発ライフを^^
Vue.js+TypeScriptで開発するときの参考記事まとめ
https://qiita.com/kai_kou/items/19b494a41023d84bacc7