Vue.js做todo日常事务任务列表
目标:用Vue.js制作一个todo任务列表功能:1.增删便签任务2. 编辑便签任务3. 深度监控数据4. 利用hash过滤数据知识点:1. 常见指令的使用2. 双向数据绑定(v-model)3. 动态添加class4. 循环(v-for)5. 数据监控5. 自定义属性6. 过滤器7. 计算属性8. hash过滤数据
·
目标:用Vue.js制作一个todo任务列表
功能:
1.增删便签任务
2. 编辑便签任务
3. 深度监控数据
4. 利用hash过滤数据
知识点:
1. 常见指令的使用
2. 双向数据绑定(v-model)
3. 动态添加class
4. 循环(v-for)
5. 数据监控
5. 自定义属性
6. 过滤器
7. 计算属性
8. hash过滤数据
9. 事件修饰符
最终效果:
未添加任务前:
添加3个任务:
标记一个已完成:
筛选未完成任务
筛选已完成任务
html代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<section>
<div class="page-top">
<div class="page-content">
<h2>任务计划列表</h2>
</div>
</div>
<div class="main" id="main">
<h3 class="title">添加任务</h3>
<!--:keyup.enter事件修饰符的用法-->
<input type="text" class="task-input" placeholder="输入任务,按下回车键即可添加新任务" v-model='todo' v-on:keyup.enter='addTodo' />
<ul class="task-count" v-show='list.length'>
<li><strong style="color: #EE0000;">{{noCheckedNum}}</strong>个任务未完成</li>
<li class="action">
<a href="#all" :class="{active:visibility === 'all'}">所有任务</a>
<a href="#unfinished" :class="{active:visibility === 'unfinished'}">未完成</a>
<a href="#finished" :class="{active:visibility === 'finished'}">已完成</a>
</li>
</ul>
<h3 class="title">任务列表</h3>
<div class="tasks">
<span class="no-task-tip" v-show='!list.length'>还没有添加任何任务</span>
<ul class="todo-list">
<li class="todo" v-bind:class='{completed: item.isChecked,editing: item === editTodos}' v-for='item in filteredList'>
<div class="view">
<input type="checkbox" class="toggle" v-model='item.isChecked' />
<label for="" @dblclick="editTodo(item)">{{item.title}}</label>
<a class="destroy" v-on:click='deleteTodo(item)'></a>
</div>
<input type="text" class="edit" v-myfocus='editTodos === item' v-on:blur='edited(item)' v-on:keyup.13='edited(item)' v-on:keyup.esc='cancelEdit(item)' v-model='item.title' />
</li>
</ul>
</div>
</div>
</section>
<script src="app.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
JavaScript代码:
//存取localStorage中的数据
var store = {
save(key, value) { //存数据
localStorage.setItem(key, JSON.stringify(value));
},
fetch(key) { //取数据
return JSON.parse(localStorage.getItem(key)) || [];
}
}
//所有的list
var list = store.fetch('vue-dotolist'); //fetch的key值可自定义
//过滤任务的三种状态
var filter = {
all: function(list) {
return list;
},
unfinished: function(list) {
return list.filter(function(item) {
return !item.isChecked;
});
},
finished: function(list) {
return list.filter(function(item) {
return item.isChecked;
});
}
};
var vm = new Vue({
el: '.main',
data: {
list: list,
todo: '', //记录新增任务的数据
editTodos: '', //记录正在编辑任务的数据
beforTitle: '', //记录正在编辑的数据的原title
visibility: 'all' //通过这个属性值的变化对数据筛选
},
watch: {
//浅复制
/*list: function(){ //监控list属性,当该值发生变化时调用函数
store.save('vue-dotolist', this.list);
}*/
//深复制
list: {
handler: function() {
store.save('vue-dotolist', this.list);
},
deep: true
}
},
methods: {
addTodo(e) { //添加任务
//向list中添加一项任务
//事件处理函数中的list指向的是当前根实例
this.list.push({
title: this.todo,
isChecked: false //新增任务默认不勾选
});
this.todo = '';
},
deleteTodo(todo) { //删除任务
var index = this.list.indexOf(todo); //找出在数组中的下标
this.list.splice(index, 1);
},
editTodo(todo) { //编辑任务
// console.log(todo);
//编辑任务时先记录这条任务的title,以便取消编辑时能保留之前的title
this.beforTitle = todo.title;
this.editTodos = todo;
},
edited(todo) { //编辑完成
//按下enter键(keyCode为13)或者失去焦点完成编辑
this.editTodos = '';
},
cancelEdit(todo) { //按下esc键取消编辑,保持原任务内容
todo.title = this.beforTitle;
this.beforTitle = '';
//让div显示出来,input隐藏掉,也就是去掉li的class名editing
this.editTodos = '';
}
},
computed: { //计算属性
noCheckedNum: function() { //计算未完成任务数
return this.list.filter(function(item) { //筛选出isChecked为false的任务,即未完成
return !item.isChecked
}).length
},
filteredList: function() { //过滤任务状态
//找到过滤函数就返回过滤后的数据,如果没有则返回所有函数
return filter[this.visibility] ? filter[this.visibility](list) : list;
}
},
directives: { //自定义事件,
'myfocus': { //自定义事件名称
update(el, binding) { //数据更新时
// console.log(binding); //可查看到value属性值
if (binding.value) { //如果value属性值为true执行获取焦点focus
el.focus();
}
}
}
}
});
// 监测hash改变,过滤任务
function watchHashChange() {
var hash = window.location.hash.slice(1);
vm.visibility = hash;
console.log(hash)
}
//进入页面就执行函数
watchHashChange();
//hash改变时也执行函数
window.addEventListener('hashchange', watchHashChange);
CSS代码
ul, li {
list-style: none;
}
section {
display: block;
width: 300px;
margin: 30px auto;
text-align: center;
}
.main input[class='task-input'] {
line-height: 24px;
width: 230px;
height: 24px;
padding: 3px;
outline: none;
}
.title {
color: #008b8b;
}
.task-count li {
margin-top: 10px;
}
.action a {
text-decoration: none;
}
.active{
border: 1px solid #B22222;
border-radius: 3px;
padding: 3px;
}
.completed .view label {
text-decoration: line-through;
color: #aaa;
}
input.edit {
display: none;
height: 24px;
}
.todo-list li {
text-align: left;
}
.editing {
text-align: center;
}
.editing div.view {
display: none;
}
.editing .edit {
display: block;
text-align: center;
}
.view input, .view label, .view a {
line-height: 20px;
height: 20px;
vertical-align: middle;
}
a.destroy {
display: inline-block;
width: 20px;
background: url(dele.png) no-repeat center center;
}
更多推荐
已为社区贡献2条内容
所有评论(0)