(第5回)フロントエンド開発のすすめ【Vue.js編 その1】

(第5回)フロントエンド開発のすすめ【Vue.js編 その1】

目次

回の目標
Visual Studio Code から開発環境を起動させる
ファイルの削除と追加
実装
 - main.jsの変更
 - 画面と作業内容の作成
 - 削除機能の追加
次回予告

今回の目標

今回の完成イメージ。
とてもシンプルな画面構成です。

第1回でVue.jsの雛形プロジェクトを作成しましたので、こちらをベースに編集を行います。

第1回の記事はこちら ↓



※2020年6月22日現在、Vue.jsのコマンドラインツールを最新のVue CLI 4.4.4にアップデートして雛形プロジェクトを作成しています。 バージョンが古い場合は、アップデートを行ってください。
アップデートの手順は下記となります。

// Vue CLIの現在のバージョンを確認する
vue --version
// Vue CLIのアップデート
npm install -g @vue/cli

アップデート後、Vue CLI のバージョンを確認し、
Vue CLI のバージョンが更新されていることを確認してください。


Visual Studio Code から開発環境を起動させる

Visual Studio Code を開き、「ファイル」→「フォルダを開く」でフォルダの選択ダイアログが開くので、第1回で作成したvue-appのフォルダを指定します。
その後「ターミナル」→「新しいターミナル」を選択します。

画面下部にターミナルのウィンドウが表示後、 vue-appのディレクトリ指定されていることを確認し、
「npm run serve」とコマンドを入力します。

PS C:(任意のディレクトリ)\vue-app> npm run serve

以下のように表示されたらブラウザで確認できるようになります。
「Local」に記載されたURLをブラウザで入力し、表示されるか確認してください。

INFO  Starting development server...
98% after emitting CopyPlugin

DONE  Compiled successfully in 1968ms
12:40:14

  App running at:
  - Local:   http://localhost:(ポート番号)/
  - Network: http://(IPアドレス):(ポート番号)/

※Visual Studio Codeでの開発環境の起動の詳細は第2回をご覧ください。
 ただし、第2回はReactのプロジェクトを開いていますので、コマンドが異なります。

第2回の記事はこちら ↓

ファイルの削除と追加

雛形プロジェクトのなかで不要なファイルを削除しましょう。
まずlogo.pngHelloWorld.jsApp.vueの3ファイルを削除します。

次に既存のcomponents配下に main.vueinputTask.vueを追加します。
main.vueは画面全体を構成するコンポーネント、inputTask.vueファイルは作業内容を構成するコンポ―ネントとして使用します。

赤が削除するファイル、青が追加するファイル

実装

ファイル整理後は、実際にコードを変更していきます

main.jsの変更

React編のindex.jsにあたり、最初に読み込まれて実行されるエントリーポイントです。
初期ではAPPコンポーネントが挿入されていますが、日報アプリ用のDairyReportコンポーネントを作成したいと思います。
このDairyReportを画面全体を構成する親コンポーネントとしていきます。

// 変更前(main.js)
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')
// 変更後(main.js)
import Vue from 'vue'
import DairyReport from './components/main.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(DairyReport),
}).$mount('#app')

画面と作業内容の作成

次に画面を構成する単一ファイルコンポーネントmain.vueと作業内容を構成するinputTask.vueを変更していきます。
単一ファイルコンポーネントはHTML, JavaScript, CSSで構成され、ファイルの拡張子は.vueとなります。
下記は<template>と<script>のみですが、<style>は本稿の最後に追加します。

<!-- main.vue -->
<template>
  <div>
      <h1>Vue.js DairyReport</h1>
      <h2>本日の作業</h2>
      <Task />
  </div>
</template>

<script>
import Task from './inputTask';

export default {
  name: 'App',
  components: {
    Task
  }
}
</script>


inputTask.jsは見やすいように<template>部分と<script>部分を分けています。

<!-- inputTask.vue -->
<template>
<div>
  <div v-for="count in defCount" class="form" v-bind:key="count.index">
    <select>
      <option disabled value="" selected>選択して下さい</option>
      <option v-for="(option, index) in projectList" :key="index">
        {{ option.name }}
      </option>
    </select>
      <select>
      <option disabled value="" selected>選択して下さい</option>
      <option v-for="(option, index) in taskList" v-bind:value="option.name" v-bind:key="index">
        {{ option.name }}
      </option>
    </select>
    <input type="text" name="detail" placeholder="備考" />
  </div>
</div>
</template>
<script>

const PROJECT_LIST = [
  {name:"工程管理システム"},
  {name:"勤怠管理システム"},
  {name:"会議共有システム"},
  {name:"社内システム"}
];

const TASK_LIST = [
  {id:1, name:"仕様書作成"},
  {id:2, name:"製造"},
  {id:3, name:"テスト"},
  {id:4, name:"打ち合わせ"}
];

const DEF_ROWS = [
  {index:1},
  {index:2},
  {index:3}
];

export default {

  data () {
    return {
      defCount: []
    }
  },
  created() {
    this.projectList = PROJECT_LIST;
    this.taskList = TASK_LIST;
    this.defCount = DEF_ROWS;
  }
}
</script>

React編と異なり、こちらのファイルに画面上で使用するドロップダウンリストの項目を定義しています。

セレクトボックスとテキストボックスを追加
次は行の削除ボタンを追加する

削除ボタンの追加

次にそれぞれの作業ごとに削除ボタンを設置して、項目を削除できるようにしていきましょう。
inputTask.vueに削除処理を追加していきます。
以下、<template>部分と<script>に分けています

<!-- inputTask.vue -->
<template>
<div>
  <div v-for="(count, index) in defCount" class="form" v-bind:key="count.index">
    <select>
      <option disabled value="" selected>選択して下さい</option>
      <option v-for="(option, index) in projectList" :key="index">
        {{ option.name }}
      </option>
    </select>
      <select>
      <option disabled value="" selected>選択して下さい</option>
      <option v-for="(option, index) in taskList" v-bind:value="option.name" v-bind:key="index">
        {{ option.name }}
      </option>
    </select>
    <input type="text" name="detail" placeholder="備考" />
    <button v-on:click="deleteTask(index)">削除</button>
  </div>
</div>
</template>
(省略)

3行目v-forディレクティブにパラメータを追加しています。第2引数には配列のインデックスを受け取れるため、17行目で追加したdeleteTaskメソッドにパラメータとして渡すことで、削除対象の行を特定しています。
なお、このindexをkey属性にセットすると、削除の動作がおかしくなるため注意が必要です。

(省略)
export default {

  data () {
    return {
      defCount: []
    }
  },
  created() {
    this.projectList = PROJECT_LIST;
    this.taskList = TASK_LIST;
    this.defCount = DEF_ROWS;
  },
  methods: {
    deleteTask(index) {
      this.defCount.splice(index, 1);
    }
  }
}
</script>

タスクを削除するメソッドを追加しました。

これで削除処理が実装されました


最後に、項目がくっついている状態なので、調整しておきます。
ReactではCSS用のファイルで調整を行いましたが、inputTask.vueに<style>タグを追加してコンポーネントとして管理しやすいようにしておきます。
以下では<script>タグの下に追加しています。

(省略)
</script>

<style>
/* 要素間のマージン調整 */
select,
button,
text {
  margin-right: 5px;
  margin-left: 5px;
}
select,
button {
  height: 25px;
}
text {
  height: 20px;
}
</style>
項目間の幅を若干調整して見やすくなりました

次回予告

今回は日報アプリをVue.jsを用いた場合の実装を行いました。
項目の変更、削除ができるようになりましたので、次はReact同様に項目の追加など機能を増やして紹介していく予定です。