【Vue.js】Vue.jsを使ってToDoアプリを作ってみた

Vue.jsを使って以下のようなToDoアプリを作成しました。

コードの全量を載せているので[jsfiddle](https://jsfiddle.net)などで
ぜひアプリの挙動を確認してみてください！

※今回はサーバーサイドの実装をしていないので
　リロードすると追加したタスクは消えてしまいます。

![ToDo app.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1418672/bbea15a8-a133-4936-0a00-99a0d2641212.gif)

#コード全量
```html:index.html
<head>
    <meta charset="UTF-8" />
    <title>ToDoアプリ</title>
</head>
<body>
    <div id="app">
      <article class="wrap">
          <section class="todo-form">
              <p class="todo-title">ToDoリスト</p>
              <input
              type="text"
              name="todo-text"
              class="input-text"
              placeholder="入力してください"
              :value="text"
              @input="inputText"
              />
              <button class="add-button" @click="addTodo">追加</button>
          </section>
          <section class="list-area">
              <div class="area-todo">
                  <ul class="todo-area">
                      <li
                        v-for="(item, i) in todos"
                        :key="i"
                        class="list"
                      >
                      <span class="list-label">{{item.text}}</span>
                      <span class="button-area">
                          <button class="list-button button-done" @click="doneTodo(item.id)">完了</button>
                      </span>
                      </li>
                  </ul>
              </div>
          </section>
      </article>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="script.js"></script>
</body>

<style scoped>
.wrap {
  width: 960px;
  height: auto;
  padding: 0 0 50px;
  margin: 0 auto;
}

.todo-form {
  text-align: center;
  padding: 80px 0 50px;
}

.todo-form>.add-button {
  margin-left: 18px;
}

.input-text {
  width: 300px;
  font-size: 20px;
  padding: 12px 20px;
  border-radius: 4px;
  -webkit-appearance: none;
  border: none;
  box-shadow: 0px 0px 12px #ccc;
}

.add-button {
  font-size: 20px;
  padding: 12px 20px;
  border: none;
  -webkit-appearance: none;
  background: #3399FF;
  color: #eee;
  border-radius: 4px;
}

.list {
  align-items: center;
  background: #fefefe;
  box-shadow: 0px 2px 12px #cecece;
  display: flex;
  justify-content: space-between;
  list-style: none;
  padding: 10px 20px 10px 32px;
  width: 50%
}

.list:not(:first-child) {
  margin-top: 16px;
}

.list-label {
  font-size: 28px;
}

.list-button {
  -webkit-appearance: none;
  font-size: 20px;
  padding: 8px 16px;
  border-radius: 4px;
  border: none;
  color: #222;
  background: #eee;
}

.list-button.button-done {
  background:#FF9966;
  color: #eee;
}

.todo-title {
  color: #444444;
  font-size: 35px;
  font-weight:700; 
}

.todo-area {
  margin-top: 15px;
  padding: 0 0 0 277;
}
</style>
```

```javascript:script.js
new Vue({
    el: '#app',
    data() {
        return {
            todos: [],
            text: ''
        };
    },
    methods: {
        inputText(e) {
            this.text = e.target.value;
        },
        addTodo() {
            if (!this.text) return;
            const text = this.text;
            const id = Math.ceil(Math.random() * 1000);
            const todo = {
                id,
                text
            };
            this.todos.push(todo);
            this.resetText();
        },
        resetText() {
            this.text = '';
        },
        doneTodo(id) {
            const index = this.getIndexBy(id);
            this.todos.splice(index, 1);
        },
        getIndexBy(id) {
            const filteredTodo = this.todos.filter(todo => todo.id === id)[0];
            const index = this.todos.indexOf(filteredTodo);
            return index;
        },
    }
});
```
#参考
[書籍「たった1日で基本が身に付く！Vue.js超入門」](https://www.amazon.co.jp/たった1日で基本が身に付く！-Vue-js-超入門-石亀-広大-ebook/dp/B089LDYFV1)