共计 4814 个字符,预计需要花费 13 分钟才能阅读完成。
gitHub 地址:https://github.com/gaozhixiao…
功能拆分:
- 渲染数据
- 键盘事件:添加事项
- 鼠标点击事件:移除事项
- 显示未办事项数据
- 全部事项、未办事项、已办事项状态切换
- 清除全部完成事项
- 全选、取消全选
- LocalStorage 读取,保存事项数据
- 鼠标双击事件:双击修改数据
- 键盘事件:Enter 键盘事件完成修改
- 键盘事件:Esc 键盘事件取消修改
- 自定义事件
- 加载事件:获取焦点
- 失去焦点事件:保存事项
1 渲染数据
指令:v-for v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名
指令:v-bind v-bind:class = {} 动态绑定 class。缩写为:class
<li
class="todo"
v-for="(item, index) in todoList"
:key="index"
:class="{completed: item.selected}"
<div class="view">
<input
class="toggle"
type="checkbox"
>
<label
>{{item.title}}</label>
<button
class="destroy"
></button>
</div>
</li>
数据:
{
id: 1,
title: "todo1",
selected: false
}
2 Enter 键盘事件:添加事项
指令:v-on v-on 指令监听 DOM 事件。缩写为 @
按键修饰符: .enter: enter 按键按下时触发
指令:v-model 双向数据绑定,它会根据控件类型自动选取正确的方法来更新元素
<input
class="new-todo"
autofocus
autocomplete="off"
placeholder="What needs to be done?"
@keyup.enter="add"
v-model="todoValue"
>
add: function () {
let todoLength = this.todoList.length;
this.todoList.push({
"id": todoLength + 1,
"title": this.todoValue,
"selected": false
})
this.todoValue = ""
},
3 鼠标点击事件:移除事项
<button
class="destroy"
@click="remove(index)"
></button>
remove: function (index) {this.todoList.splice(index, 1);
},
4 显示未办事项数目
// 未办事项
unSeleted: function () {return this.todoList.filter((item, index, array) => {return !item.selected;})
},
<span class="todo-count">
<strong>{{unSeleted.length}}</strong> item left
</span>
5 全部事项、未办事项、已办事项状态切换
Hash:hash 是 url 的一部分,从 #开始
Array.filter: array.filter(function(currentValue,index,arr), thisValue) filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
_.filter: _.filter(collection, [predicate=_.identity])。引自:lodash.js 参考地址:https://www.lodashjs.com/
// 将状态栏设置成 hash 属性
<a
href="#/all"
:class="{selected: hashActive ==='all'}"
>All</a>
// 默认状态为全部事项
hashActive: "all"
// 已办事项
selelted: function () {return _.filter(this.todoList, function (item) {return item.selected;})
},
// 未办事项
unSeleted: function () {return this.todoList.filter((item, index, array) => {return !item.selected;})
},
// 事项状态切换
hashFilter: function () {if (this.hashActive === 'all') {return this.todoList;} else if (this.hashActive === 'active') {return this.unSeleted;} else if (this.hashActive === 'completed'){return this.selelted;} else {return this.todoList;}
}
// 已办事项,未办事项返回值都是一个数组,故更新渲染数据
<li
class="todo"
v-for="(item, index) in hashFilter"
:key="index"
:class="{completed: item.selected}"
>
6 清除全部完成事项
指令:v-if: v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。
<button
class="clear-completed"
@click="clearCompleted"
v-if="selelted.length"
>
Clear completed
</button>
// 清空已办事项
clearCompleted: function () {this.todoList = this.unSeleted;},
7 全选、取消全选
Array.foreach: array.forEach(function(currentValue, index, arr), thisValue) forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
// 当事项未全部选择时 -> 全选,反之,反选
<input
id="toggle-all"
class="toggle-all"
type="checkbox"
@click="toggleAll"
>
toggleAll: function () {let selectedAll = this.todoList.every(function (item, index, array) {return item.selected;})
if (selectedAll) {
this.todoList.forEach(item => {item.selected = false;});
} else {
this.todoList.forEach(item => {item.selected = true;});
}
},
8 LocalStorage 读取,保存事项数据
localStorage.getItem: var aValue = localStorage.getItem(keyName); 从 localStorage 中读取数据
localStorage.setItem: localStorage.setItem(keyName, keyValue); 写入到 localStorage 中
// LocalStorage 读取事项
let todoList = localStorage.getItem('todoList');
if (todoList) {todoList = JSON.parse(todoList)
} else {todoList = [];
}
// 渲染数据修改为从 localStorage 中获取
data: {todoList: todoList},
// 保存事项到 localStorage, 采用监听属性对象内部的改变
watch: {
todoList: {
deep: true,
handler: function () {localStorage.setItem('todoList', JSON.stringify(this.todoList));
}
}
},
9 鼠标双击事件:双击修改数据
// 双击事件
<label
v-on:dblClick="edit(item, $event)"
>{{item.title}}</label>
// 双击后,修改框显示双击前的数据
// 此处注意的是:绑定的是 item 数据,这样做可以任意修改该条数据
<li
class="todo"
v-for="(item, index) in hashFilter"
:key="index"
:class="{completed: item.selected, editing: editValue === item}"
>
edit: function (item, el) {
this.editValue = item;
this.cancelValue = item.title;
},
<input
class="edit"
type="text"
v-model="item.title"
>
10 键盘事件:Enter 键盘事件完成修改
<input
class="edit"
type="text"
v-model="item.title"
@keyup.enter="editDone(item, index)"
>
// 当编辑的数据为空时,删除该条数据, 同时重置该属性
editDone: function (item, index) {if (!item.title) {this.todoList.splice(index, 1)
}
this.editValue = ""
},
11 键盘事件:Esc 键盘事件取消修改
按键修饰符: .Esc: Esc 按键按下时触发
<input
class="edit"
type="text"
v-model="item.title"
@keyup.enter="editDone(item, index)"
@keyup.esc="cancelDone(item, index)"
>
cancelDone: function (item, index) {
item.title = this.cancelValue;
this.editValue = "";
this.cancelValue = "";
}
12 自定义事件
自定义指令: directives
// 当双击修改事项时,获取焦点
<input
class="edit"
type="text"
v-model="item.title"
v-todo-focus="editValue == item"
@keyup.enter="editDone(item, index)"
@keyup.esc="cancelDone(item, index)"
>
todoFocus: function (el) {el.focus();
}
13 加载事件:获取焦点
window.onload:文档加载完成后执行
// 程序加载,获取焦点
function getFocus () {let newTodo = document.getElementsByClassName('new-todo')[0];
newTodo.focus();}
window.onload = getFocus;
// 切换状态,获取焦点
hashFilter: function () {getFocus();
...
}
14 失去焦点事件:保存事项
<input
class="edit"
type="text"
v-model="item.title"
v-todo-focus="editValue == item"
@blur="editDone(item, index)"
@keyup.enter="editDone(item, index)"
@keyup.esc="cancelDone(item, index)"
>