作成者別アーカイブ: sugiyamat

Vue 3でWebアプリを作ってみる

Vue CLI3がリリースされてちょっと経ちました。(記載時点で3.1.3)
色々と機能追加されていますが、その中でも大きな特徴の一つのVue UI、TypeScriptを使ってPokeAPIを呼ぶアプリを作ってみます。

以下を使ったアプリになる予定です。

  • Vue.js
  • TypeScript
  • Vuex
  • Vue Router

準備

まず、以下コマンドでVue CLIをインストールしておきます。(node、npmは前提とします)
$ npm i -g @vue/cli
vue cliのバージョンが3以上であることを確認してください。
$ vue -V

Vue UIを使ってプロジェクトの設定を行う

インストールが無事出来たらvue uiを立ち上げます。
$ vue ui

ブラウザが自動的に立ち上がります。(立ち上がらない場合はコンソールに表示されるURLで開くこともできます)
なお、$ vue ui --port 8001というようにポート指定することも可能です。
画面右下のボタンでダークモードと切り替えることが可能です。

「作成タブ」からプロジェクトの作成を開始します。VueCLIにおけるcreateコマンドの内容をGUIで設定していきます。

パッケージマネージャや機能等、ナビゲート方式で画面に表示されていくため非常にわかりやすいです。(ここでの設定内容は後で画面から変更することも可能です)

今回は以下のプラグインをインストールしました。

  • Babel
  • TypeScript
  • Router
  • Vuex
  • Linter / Formatter

プロジェクトの作成が終われば各ファイルが自動的に作成されています。(vue createが完了したのと同じ状態です)

Vue UIからは、プラグインの追加、設定を行う事が可能です。また、scriptsをタスクとしてGUIで実行することが出来ます。

このように今までCUIで出来ていたことがGUIになっており、見やすさ、分かりやすさは格段に向上します。初めてVue.jsを触るような人には非常に有用なのではないでしょうか。

作成するアプリについて

以下のように、一覧↔詳細画面を表示するだけの単純なアプリです。

最終的なファイル構成は以下のようになります。
src
┣store
┃┣modules
┃┃┣detail.ts :詳細画面用のstateを管理
┃┃┗list.ts :一覧画面用のstateを管理
┃┣index.ts :子モジュールをまとめる
┃┗root.ts :RootStateインターフェース
┣views
┃┣components
┃┃┗ListLine.vue :一覧の1行を表示するコンポーネント
┃┣Detail.vue :詳細画面表示コンポーネント
┃┗List.vue :一覧画面表示コンポーネント
┣App.vue :ルートView
┣main.ts :ルートViewをhtmlにマウント
┣router.ts :routerを管理
┣shims-tsx.d.ts :型定義
┗shims-vue.d.ts :型定義

また、package.jsonは以下のようになります。

{
  "name": "pokemon",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "axios": "^0.18.0",
    "vue": "^2.5.17",
    "vue-class-component": "^6.0.0",
    "vue-property-decorator": "^7.0.0",
    "vue-router": "^3.0.1",
    "vuex": "^3.0.1",
    "vuex-class": "^0.3.1"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.2.0",
    "@vue/cli-plugin-eslint": "^3.2.1",
    "@vue/cli-plugin-typescript": "^3.2.0",
    "@vue/cli-service": "^3.2.0",
    "@vue/eslint-config-prettier": "^4.0.0",
    "@vue/eslint-config-typescript": "^3.2.0",
    "babel-eslint": "^10.0.1",
    "eslint": "^5.8.0",
    "eslint-plugin-vue": "^5.0.0-0",
    "typescript": "^3.0.0",
    "vue-template-compiler": "^2.5.17"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "@vue/prettier",
      "@vue/typescript"
    ],
    "rules": {},
    "parserOptions": {
      "parser": "typescript-eslint-parser"
    }
  },
  "postcss": {
    "plugins": {
      "autoprefixer": {}
    }
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}

VueUIのコンソールから”Axios”や”vuex-class”等を別途追加しています。
ソースはここにアップしてあります。

サンプルとしてList.vueのソースを掲載します。

<template>
  <div>
    <div class="header">
      <span class="before" @click="nextPage();"><<</span>
      <span class="title">Pokemon List</span>
      <span class="after" @click="beforePage();">>></span>
    </div>
    <div class="list">
      <list-line
        v-for="pokemon in list.currentList"
        :key="pokemon.name"
        :name="pokemon.name"
        :index="pokemon.index"
      />
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import ListLine from "./components/ListLine.vue";
import { State, Action, Getter } from "vuex-class";
import { ListState } from "@/store/modules/list";
const namespace: string = "list";

@Component({
  components: {
    ListLine
  }
})
export default class List extends Vue {
  @State("list") list!: ListState;
  @Action("loadList", { namespace }) loadList!: () => void;
  @Action("setPage", { namespace }) setPage!: (page: number) => void;

  created() {
    this.loadList();
  }
  nextPage() {
    this.setPage(this.list.currentPage - 1);
  }
  beforePage() {
    this.setPage(this.list.currentPage + 1);
  }
}
</script>

<style scoped>
.header {
  height: 30px;
  border-bottom: 1px solid gray;
}
.title {
  margin: auto;
}
.before {
  float: left;
  cursor: pointer;
}
.after {
  float: right;
  cursor: pointer;
}
</style>

TypeScriptでVuexのState,Actionを利用・実行するようなものになっています。

  • createdでインスタンス生成時にポケモン一覧をAPIで取得
  • nextPage,beforePageでページ遷移(アクション実行)

といった機能があります。アクションの中ではAPI実行等の処理を行った後、mutationsをcommitしてstateの変更を行っています。

作成したWebアプリ

Vue UIのプロジェクトタスク>serve>タスクの開始でサーバーを起動することができます。また、「アプリを開く」でブラウザをここから立ち上げることも可能です。

実際に立ち上げると以下のような画像になります。

ポケモンをクリックすると詳細画面になります。こちらは日本語の情報が取得出来るため日本語にしています。

TypeScript、class-componentが使えることにより、Angularが出来る人ならよりVueにとっかかりやすくなったと思います。ソースの見晴らしも似たものにすることが出来ますし。

TypeScriptでタイプセーフなプログラムがしやすくなりましたが、VuexでActionにdispatchするところや、html-template内の部分等タイプセーフになっていない(ビルド時ではなく、ブラウザで動かして初めてエラー検知される)部分がまだまだあるので。そこら辺は今後改善されていくんだろうと思います。

Vue UI自体はCLIをGUIにしただけのものですが、見やすさ、分かりやすさでは他ライブラリ(Angular、React)に並ぶものはないのではないかと思いました。

 

参考URL: