学习 Vue.js:写一个简单的 Todo 小样
这是学习 Vue.js 的一个小样,最后的结果在 codepen.io 上能看到。需要引入 Bootstrap 样式文件和 Vue.js 库。
再稍微加点自定义样式。
body {
margin-top: 20px;
}
.btn-xs+.btn-xs {
margin-right: .5rem;
}
a.list-group-item.completed {
background-color: #f5f5f5;
text-decoration: line-through;
}
架构
HTML
<div id="todoApp" class="container">
<div class="panel panel-default">
<div class="panel-heading text-center">
计划要做的事情,共 0 件
</div>
<div class="panel-body">
<div class="list-groups">
<a class="list-group-item">
;)
</a>
</div>
</div>
<div class="panel-footer">
<form>
<div class="form-group">
<input type="text" class="form-control text-center">
</div>
<button class="btn btn-default btn-block" type="submit">添加</button>
</form>
</div>
</div>
</div>
JavaScript
new Vue({
el: '#todoApp',
data: {
todos: [
{title: '吃早饭', completed: false},
{title: '吃午饭', completed: false},
{title: '吃晚饭', completed: false}
],
newTodo: {title: '', completed: false},
},
methods: {}
});
循环打印 todos 列表
<div class="panel-heading text-center">
计划要做的事情,共 {{ todos.length }} 件
</div>
<a class="list-group-item" v-for="(todo, index) in todos">
{{ todo.title }}
</a>
添加 Todo
<form v-on:submit.prevent="add">
<div class="form-group">
<input type="text" class="form-control text-center" v-model="newTodo.title">
</div>
<button class="btn btn-default btn-block" type="submit">添加</button>
</form>
input
输入框绑定了 newTodo.title
的值。表单提交时,执行 add
方法。
methods: {
add() {
if (! this.newTodo.title.trim()) { return ; }
this.todos.push({
title: this.newTodo.title,
completed: this.newTodo.completed
});
this.newTodo.title = '';
}
}
删除 Todo
<a class="list-group-item" v-for="(todo, index) in todos">
{{ todo.title }}
<button class="btn btn-xs btn-danger pull-right" v-on:click='destroy(index)' title="删除">✘</button>
</a>
点击删除按钮,执行 destroy
方法。
destroy(index) {
this.todos.splice(index, 1);
}
标记 Todo 完成/未完成
<a class="list-group-item" v-bind:class="{ 'completed': todo.completed }" v-for="(todo, index) in todos">
{{ todo.title }}
<button class="btn btn-xs btn-danger pull-right" v-on:click='destroy(index)' title="删除">✘</button>
<button class="btn btn-xs pull-right" v-on:click='toggleDone(index)' v-bind:class="[todo.completed ? 'btn-success': '']" v-bind:title="[todo.completed ? '点击,标记为未完成': '点击,标记为已完成']">✔</button>
</a>
标记 Todo 使用 toggleDone
方法。
toggleDone(index) {
this.todos[index].completed = !this.todos[index].completed;
}
上移、下移 Todo
<button class="btn btn-xs btn-info pull-right" v-on:click='down(index)' title="下移">↓</button>
<button class="btn btn-xs btn-info pull-right" v-on:click='up(index)' title="上移">↑</button>
上移
执行 up
方法。
up(index) {
if (index - 1 < 0) { return ; }
var temp = this.todos[index];
this.todos[index] = this.todos[index-1];
this.todos[index-1] = temp;
this.todos = [].concat(this.todos);
}
下移
执行 down
方法。
down(index) {
if (index + 1 >= this.todos.length) { return ; }
var temp = this.todos[index];
this.todos[index] = this.todos[index+1];
this.todos[index+1] = temp;
this.todos = [].concat(this.todos);
}
需要注意的是,上移和下移方法中,最后都生成新的 todos
,否则数组中元素位置的调整,不会引页面重绘。
this.todos = [].concat(this.todos);
本作品采用《CC 协议》,转载必须注明作者和本文链接