LoginSignup
0
1

More than 3 years have passed since last update.

Vue.jsの基本的な機能だけでTODOリストを作成する

Last updated at Posted at 2020-04-04

See the Pen Vue.js practice20200404 by tseno (@tseno) on CodePen.

解説

チェックをつけると取り消し線がつく

  • チェックをつけるとv-model="item.check"で、dataの値が変わる。(双方向データバインディング)
  • dataのitem.checktrueのときに、class="checked"が適用される。(HTML クラスのバインディング)
一部のみ
  <style type="text/css">
    <!--
    .checked {
      text-decoration: line-through;
    }
    -->
  </style>
<div v-for="(item, i) in items" :key="item.text">
  <label :class="{checked: item.check}">
    <input type="checkbox" v-model="item.check" />
</div>

追加ボタンは、必須入力項目を入力しないと有効化されない

  • 算出プロパティaddButtonDisabledで、テキストボックスと日付入力が空の場合は、disabled="true"(追加ボタンを無効)にしている。
一部のみ
    <button @click="onClick" :disabled="addButtonDisabled">追加</button>

  <script>
    var vm = new Vue({
      computed: {
        addButtonDisabled: function() {
          return this.addText.length === 0 || this.addDate == null;
        }
      }
    })
  </script>

追加ボタンで追加する

  • 追加ボタンをクリックするとonClickイベントを呼び出す。
  • dataのitemsの配列に追加(push)。テキストボックスと日付入力を空にする。
一部のみ
    <button @click="onClick" :disabled="addButtonDisabled">追加</button>

  <script>
    var vm = new Vue({
      methods: {
        onClick: function() {
          this.items.push({
            text: this.addText,
            check: false,
            dueDate: this.addDate,
          });
          this.addText = "";
          this.addDate = null;
        }
    })
  </script>

[X]ボタンで削除する

  • [X]ボタンをクリックするとonDelete(i)イベントを呼び出す。(何番目かを引数で渡す)
  • dataのitemsの配列からi番目の要素を削除(splice)。
一部のみ
    <button @click="onDelete(i)">X</button>

  <script>
    var vm = new Vue({
      methods: {
        onDelete: function(i) {
          this.items.splice(i, 1);
        }
    })
  </script>

追加・削除時にアニメーションする

  • リスト表示部分をtransition-groupタグで囲む
  • .v-enter-active .v-enter-active ゆっくり表示/非表示する時間(500ms)
  • .v-move ゆっくり動く時間(1s)
  • .v-leave-active { position: absolute; } これを入れないと、削除時にアニメーションしない
  • .v-enter .v-leave-to 表示し始めと、消え終わりのとき、透明にする(opacity: 0.0)
  • .v-enter-to .v-leave 表示し終わりと、消え始めのとき、透明にしない(opacity: 1.0)
<style type="text/css">
    <!--
    .v-enter-active,
    .v-leave-active {
      transition: opacity 500ms;
    }
    .v-move {
      transition: transform 1s;
    }
    .v-leave-active {
      position: absolute;
    }
    .v-enter,
    .v-leave-to {
      opacity: 0.0;
    }
    .v-enter-to,
    .v-leave {
      opacity: 1.0;
    }
    -->
  </style>
    <transition-group tag="div">
      <div v-for="(item, i) in items" :key="item.text">
        <label :class="{checked: item.check}">
          <input type="checkbox" v-model="item.check" />
          {{ item.text + '(' + item.dueDate.toLocaleDateString() + ')' }}
        </label>
        <button @click="onDelete(i)">X</button>
      </div>
    </transition-group>

Element UIのカレンダーを表示させる

  • Element UIをCDNから読み込む
  • ELEMENT.locale(ELEMENT.lang.ja); でカレンダーの曜日表示が日本語になる
  • el-date-picker タグで表示させる。type="date"を指定しているが、year/month/date/dates/datetime/ week/datetimerange/daterange/monthrangeのいずれかを指定できる。

    <el-date-picker v-model="addDate" type="date" placeholder="期限">
    </el-date-picker>

 <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" />
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <script src="http://unpkg.com/element-ui/lib/umd/locale/ja.js"></script>
  <script>
    ELEMENT.locale(ELEMENT.lang.ja);
  </script>

全体のソース

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8" />
  <title>TODO List 20200404</title>
  <style type="text/css">
    <!--
    .checked {
      text-decoration: line-through;
    }

    .v-enter-active,
    .v-leave-active {
      transition: opacity 500ms;
    }

    .v-move {
      transition: transform 1s;
    }

    .v-leave-active {
      position: absolute;
    }

    .v-enter,
    .v-leave-to {
      opacity: 0.0;
    }

    .v-enter-to,
    .v-leave {
      opacity: 1.0;
    }
    -->
  </style>
</head>

<body>
  <div id="app">
    <transition-group tag="div">
      <div v-for="(item, i) in items" :key="item.text">
        <label :class="{checked: item.check}">
          <input type="checkbox" v-model="item.check" />
          {{ item.text + '(' + item.dueDate.toLocaleDateString() + ')' }}
        </label>
        <button @click="onDelete(i)">X</button>
      </div>
    </transition-group>
    <input type="text" v-model="addText" />
    <el-date-picker v-model="addDate" type="date" placeholder="期限">
    </el-date-picker>
    <button @click="onClick" :disabled="addButtonDisabled">追加</button>
  </div>
  <script src="http://unpkg.com/vue/dist/vue.js"></script>
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" />
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <script src="http://unpkg.com/element-ui/lib/umd/locale/ja.js"></script>
  <script>
    ELEMENT.locale(ELEMENT.lang.ja);
    var vm = new Vue({
      el: "#app",
      data: {
        addText: "",
        addDate: "",
        items: [{
            text: "旅行の予約をする",
            check: true,
            dueDate: new Date(),
          },
          {
            text: "領収書をまとめる",
            check: false,
            dueDate: new Date(),
          },
          {
            text: "レンタカーの手配",
            check: false,
            dueDate: new Date(),
          },
          {
            text: "天気予報チェック",
            check: false,
            dueDate: new Date(),
          },
        ],
      },
      computed: {
        addButtonDisabled: function() {
          return this.addText.length === 0 || this.addDate == null;
        },
      },
      methods: {
        onClick: function() {
          this.items.push({
            text: this.addText,
            check: false,
            dueDate: this.addDate,
          });
          this.addText = "";
          this.addDate = null;
        },
        onDelete: function(i) {
          this.items.splice(i, 1);
        },
      },
    });
  </script>
</body>

</html>
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1