demo: http://hiijack.github.io/todo/index.html
更好的代码阅读体验: https://github.com/hiijack/vue-todo
截图
所有事项
已完成事项
未完成事项
核心代码:
Todo.vue
<template>
<div>
<form id="todoform">
<div class="todobox">
<input class="todo" type="text" v-model="todoText"
placeholder="待办事项"/>
<input class="addbutton" v-on:click.prevent="add"
type="submit" value="添加"/>
</div>
</form>
<todoInfo v-bind:list="list" v-on:changeShowType="changeShowType"/>
<todoList v-bind:list="list" v-bind:showType="showType"
v-on:deleteTodo="deleteTodo"/>
</div>
</template>
<script>
import TodoList from './TodoList'
import TodoInfo from './TodoInfo'
export default {
name: 'todo',
components: {
TodoList, TodoInfo
},
data() {
return {
todoText: '',
list: [],
showType: 'all'
}
},
methods: {
add() {
if (this.todoText == '') {
return;
}
let todo = {
key: Date.now(),
text: this.todoText,
done: false,
edited: false
}
let arr = [];
arr.push(todo);
this.list = this.list.concat(arr);
this.todoText = '';
},
deleteTodo(key) {
this.list = this.list.filter(item => {
return item.key != key;
});
},
changeShowType(type) {
this.showType = type;
}
}
}
</script>
<style scoped>
.addbutton {
color: #fff;
height: 41px;
width: 20%;
margin: -1px;
border-color: #42b983;
background-color: #42b983;
border-style: solid;
border-width: 10px;
float: right;
}
.todobox {
display: inline-block;
border-width: 1px;
border-style: solid;
border-color: #ccc;
width: 85%;
}
.todo {
float: left;
width: 70%;
height: 35px;
margin: 3px 1px 0 15px;
padding: 0 10px 0 0;
font-size: 16px;
outline: none;
border: 0;
box-sizing: content-box;
}
</style>
TodoList.vue
<template>
<div>
<ul>
<li v-for="ls in displayList" v-bind:class='{done: ls.done}'>
<input type="checkbox" class="checkbox" v-model="ls.done">
<label v-on:dblclick="edit(ls)" v-bind:class="{hidden: ls.edited}">{{ls.text}}</label>
<input type="text" class="edit" v-focus v-bind:class="{show: ls.edited}"
v-model="ls.text" v-on:blur="update(ls)">
<input type="button" value="x" class="delete" v-on:click="deleteTodo(ls.key)">
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'todoList',
props: ['list', 'showType'],
computed: {
displayList() {
if (this.showType == 'done') {
return this.list.filter(item => {
return item.done;
});
} else if (this.showType == 'notDone') {
return this.list.filter(item => {
return !item.done;
})
} else {
return this.list;
}
}
},
methods: {
deleteTodo(key) {
this.$emit('deleteTodo', key);
},
edit(ls) {
ls.edited = true;
},
update(ls) {
ls.edited = false;
}
},
directives: {
focus: {
update: function (el) {
el.focus()
}
}
}
}
</script>
<style scoped>
ul {
width: 90%;
padding: 0;
margin: 0;
list-style: none;
}
li {
height: 28px;
margin: 3% 0 0 10%;
text-align: left;
}
.checkbox {
margin: 5px;
}
.done {
text-decoration: line-through;
color: #ccc;
}
.delete {
float: right;
background-color: #ccc;
border-color: #ccc;
border-style: solid;
}
.edit {
margin-left: 10px;
height: 20px;
font-size: 18px;
display: none;
width:70%;
}
.show {
display: inline-block;
}
.hidden {
display: none;
}
</style>
TodoInfo.vue
<template>
<div>
<span>
<a href="#" v-on:click="changeShowType('all')">所有事项</a>:{{total}}
</span>
<span>
<a href="#" v-on:click="changeShowType('notDone')">未完成</a>:{{notDone}}</span>
<span><a href="#" v-on:click="changeShowType('done')">已完成</a>:{{done}}</span>
</div>
</template>
<script>
export default {
name: 'todoInfo',
props: ['list', 'showType'],
computed: {
total() {
return this.list.length;
},
done() {
return this.list.filter(item => {
return item.done;
}).length;
},
notDone() {
return this.list.filter(item => {
return !item.done;
}).length;
}
},
methods: {
changeShowType(type) {
this.$emit('changeShowType', type);
}
}
}
</script>
<style scoped>
span {
margin: 0 5px 0 5px;
}
a {
text-decoration: none;
color: #42b983;
font-weight: 600;
}
</style>