See the Pen Vue.js practice20200404 by tseno (@tseno) on CodePen.
解説
チェックをつけると取り消し線がつく
- チェックをつけると
v-model="item.check"
で、dataの値が変わる。(双方向データバインディング) - dataの
item.check
がtrue
のときに、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>