Vue.jsで、食べログとかによくある予約表を作ってみた

# はじめに
フロント経験は、JavaScriptとReactを触ったことがある程度です。数ヶ月後に業務で使用することを目指し、独学でVue.jsの学習をしています。

今回は、「とりあえず動く」を目標に、食べログやサロン予約ページによくある予約表を作ってみました。

初学者の方の役に立てば幸いです。エンジニアの方からは、コードに関しての指摘修正など頂けるととても嬉しいです。

# 作ったもの

[![Image from Gyazo](https://i.gyazo.com/321e6d1dac8351c2baac0451255da827.gif)](https://gyazo.com/321e6d1dac8351c2baac0451255da827)

主な機能は、以下の通りです。

- 予約一覧
- 1週間ごとの表示切替
- 選択日程表示
- moment.jsで日付管理

なお、表示のためにダミーデータを入れています。


# 環境

```
npm 6.7.0
Node.js 10.15.1 
Vue.js 2.6.10 
Vue CLI 3.12.0
```

# 主要コード
※スタイルは省略しています。

```src/App.vue
<template>
  <div id="app">
    <Reservation  v-on:send-reservation="text = $event"></Reservation>
    <p>{{text}}</p>
  </div>
</template>

<script>
import Reservation from './components/Reservation.vue'

export default {
  name: 'app',
  data() {
    return {
      text: "日程未選択です"
    }
  },
  components: {
    Reservation
  }
};
</script>
```


```src/components/Reservation.vue

<template>
  <div>
    <h2>予約一覧</h2>
    <p>
      <button @click="movePreviousWeek">前の1週間</button>
      <strong>{{startDate.format('MM')}}月</strong>
      <button @click="moveNextWeek">後の1週間</button>
    </p>
    <table border="1" align="center">
      <thead>
        <tr>
          <td></td>
          <template v-for="date in dateList">
            <th :key="date">
              {{ date }}
            </th>
          </template>
        </tr>
      </thead>
      <tbody>
        <template v-for="hourlyWorkList in hourlyWorkList">
          <tr :key="hourlyWorkList.time">
            <td>{{hourlyWorkList.time}}</td>
            <td v-for="(work, i) in hourlyWorkList.workList" :key="hourlyWorkList.time + '_' + i">
              <a @click="sendReservation(dateList[i], hourlyWorkList.time, work)">
                {{ showWorkStatus(work) }}
              </a>
            </td>
          </tr>
        </template>
      </tbody>
    </table>
    <hr>
  </div>
</template>

<script>
  import moment from 'moment'
  moment.locale('ja');

  export default {
    data(){
      return {
        dateList: [],
        weekNumber: 7,
        hourlyWorkList: []
      }
    },
    created() {
      this.setDateList(this.startDate)
      this.setHourlyWorkList()
    },
    computed: {
      startDate: {
        get() {
          return moment()
        },
        set(date) {
          this.setDateList(date)
          this.setHourlyWorkList()
        }
      }
    },
    methods: {
      moveNextWeek() {
        this.startDate = this.startDate.add(this.weekNumber, 'day')
      },
      movePreviousWeek() {
        this.startDate = this.startDate.subtract(this.weekNumber, 'day')
      },
      setDateList() {
        var dateListClone = this.dateList
        dateListClone = []
        var date = moment(this.startDate)
        dateListClone.push(date.format('MM/DD(dd)'))
        for (  var i = 0;  i < (this.weekNumber - 1);  i++  ) {
          dateListClone.push(date.add(1, 'day').format('MM/DD(dd)'))
        }
        this.dateList = dateListClone
      },
      setWorkList() {
        //ダミー配列データ生成
        var array = [];
        for (let i = 0; i < this.weekNumber; i++) {
          array.push(Math.random() < 0.5);
        }
        return array
      },
      setHourlyWorkList() {
        this.hourlyWorkList = [
          {
            time: "11:00" ,
            workList: this.setWorkList()
          },
          {
            time: "12:00" ,
            workList: this.setWorkList()
          },
          {
            time: "13:00" ,
            workList: this.setWorkList()
        }]
      },
      sendReservation(date, time, work) {
        var text = ""
        if (work == true) {
          text = date + time
        } else {
          text = "この日程は選択できません。"
        }
        this.$emit("send-reservation", text)

      },
      showWorkStatus(work) {
        return work ? "o" : "x"
      }
    }
  };
</script>
```

※全てのコードは[Github](https://github.com/shockdayukio/reservation-vuejs)に公開しています。（2019/10/26現在）

## 最後に
Vue.jsは理解がかなり簡単かつ直感的に書けるので、学習しやすい印象でした。しかし、コンポーネント間の値の受け渡しや、算出プロパティ、メソッドなど理解が難しい部分もありました。

「とりあえず動く」を重視して実装してみたので、より綺麗に素早くコードを書けるようにさらに学習を進めます。

# 参考
[Udemy Vue JS 2 入門 完全パック - もう他の教材は買わなくてOK！ (Vue Router, Vuex含む]
(https://www.udemy.com/course/vue-js-complete-guide/)

[Vue.js 公式ドキュメント](https://jp.vuejs.org/v2/guide/)