官网地址:todomvc.com/
准备工作
- 在项目目录下
右键
, 选择在集成终端中打开
:
- 从 github 克隆项目模板。
git clone https://github.com/tastejs/todomvc-app-template.git
复制代码
首先要确保电脑安装了git, git的安装可以参考: juejin.cn/post/700549…
安装完成后, 会出现如下结构:
- 进入项目目录,安装项目依赖
cd 项目目录
npm install
复制代码
- 安装 Vue.js
npm install vue
复制代码
安装完后这里出现了vue:
需求分析
- 事项列表展示
• 有事项的情况
• 没有事项的情况
- 状态栏展示
• 个数展示
• 单位处理
- 事项状态切换
• 单个事项切换
• 多个事项切换
- 事项新增
• 内容检测
• 回车新增
- 事项删除
• 单个事项删除
• 已完成事项删除
- 事项编辑
• 触发编辑
• 取消编辑
• 保存编辑
- 事项筛选
• 点击切换显示类别
• 更新渲染所有事项
- 事项数据持久化
• 读取本地存储
• 更新本地存储
功能实现
模板中我们书写js的文件是app.js, 书写首页html的页面是index.html
结构展示:
事项列表展示
• 引入 vue.js 文件,创建 Vue 实例设置挂载元素, 绑定的el是 #app
。
• 在 data 中设置 todos 存储初始数据
new Vue({
el:"#app",
data: {
// todos 用于村粗所有事项信息
todos: [
{id: 1, title: "实例内容1", completed: true},
{id: 2, title: "实例内容2", completed: true},
{id: 3, title: "实例内容3", completed: false},
{id: 4, title: "实例内容4", completed: true},
]
}
})
复制代码
在main中设置事项的视图:
-
先写一个
<ul>
, 然后通过v-for
决定生成多少个<li>
-
使用
:key
绑定唯一的id
-
:class
可以绑定对象, 在模板中如果class="complated"
表示已经完成的事项. -
这个
<input>
表示的是实力内容前面的复选框(打√部分), 我们可以使用v-model
与事件的选中状态绑定. 单个复选框选中的状态是用布尔值
表示的, 所以我们这里使用todo.completed
可以实现数据的双向绑定.
设置有无事项时的显示状态:
-
事项主体部分
main
和下面的状态栏footer
都要设置有无事项的显示. -
v-show
适合于频繁切换状态的场景. -
当
todos
没有事件时,todos.length
为0, 可以隐式转换为false
, 这时就会隐藏.
状态栏信息展示
需要实现的功能为:
• 个数展示
• 单位处理
个数展示:
两种方式:
-
使用计算属性是因为: 如果选中的事项个数没有发生变化, 可以使用之前的缓存, 提高效率.
-
计算属性必须有返回值, 所以使用
return !todo.completed;
可以获得todo.completed = false
的事项. -
思想是遍历
todos
, 对每一个传入的todo
获取它的completed
属性, 如果是false
就返回这个事项, 最后使用length
方法获得返回的所有事项的长度, 也就是个数.
最后在响应的地方调用这个计算属性的属性名就可以了.
<span class="todo-count"><strong>{{ remaining }}</strong> item left</span>
复制代码
单位处理:
视图中调用时:
<span class="todo-count"><strong>{{ remaining }}</strong> {{ pluralize() }} left</span>
复制代码
或者
<span class="todo-count"><strong>{{ remaining }}</strong> {{ pluralize('item') }} left</span>
复制代码
注意后面的部分要加括号, 否则会有问题.
注意传参的时候要加引号, 否则会undefined
事项状态切换
点击下面的事项实现全选
如果剩下的事项个数为0, 就选中.
点击全选选中所有的事项
设置 v-model 后,主动操作 toggle-all 相当于设置 allDone数据,这时需要给 allDone 设置 setter 来处理。
- value是toggle-all的状态, 选中或未选中.
事项新增
需要实现的功能为:
• 输入框内容绑定
• 回车新增事项
输入框内容绑定
在 data 中设置 newTodo 用于存储数据,并绑定给新增输入框。
<input class="new-todo" placeholder="What needs to be done?" autofocus v-model="newTodo">
复制代码
回车新增事项
输入框回车时检测内容,并根据输入内容新增事项到 todos。
在methods中添加以下方法:
-
这里id只做了简单处理, 不一定能够保证完全不重复. 如果需要完全不重复, 可以采用随机数或者时间戳的方式.
-
if
用于判断数据是否为空 -
this.newTodo = "";
是为了清空输入框的内容
在视图部分添加:
-
给刚才的
v-model.trim="newTodo"
添加.trim
..trim
鼠标修饰符用于自动过滤用户输入内容首尾两端的空格。 -
添加一个回车事件, 绑定
addTodo
方法.
<input class="new-todo" placeholder="What needs to be done?"
autofocus v-model.trim="newTodo" @keyup.enter="addTodo">
复制代码
提高效率的改进
如果在视图页面直接使用v-model.trim="newTodo"
, 那么每次在输入框中进行输入的时候(还没点击回车的情况下)都会调用trim方法去除首尾两端的空格, 实际上我们只需要在按下回车添加数据的时候去除首尾两段的空格就可以了, 因此可以将trim方法移到addTodo
方法的内部:
<input class="new-todo" placeholder="What needs to be done?"
autofocus v-model="newTodo" @keyup.enter="addTodo">
复制代码
事项删除
需要实现的功能为:
• 单个事项删除
• 已完成事项删除
单个事项删除
点击单个事项中的删除按钮时,删除 todos 中对应的对象数据。
<button class="destroy" @click="reomoveTodo(todo)"></button>
复制代码
已完成事项删除
- 已完成事项按钮的需要在具有已完成事项时显示。
todos.length > remaining
表示只有当事项总数大于剩余事项数的时候才显示. 比如一共有5个事项, 剩余了2个, 说明有3个完成了.
<!-- Hidden if no completed items are left ↓ -->
<button class="clear-completed" v-show=" todos.length > remaining">Clear completed</button>
复制代码
- 操作后,事项列表中只保留未完成事项即可。
filter
方法的返回值是一个包含了符合条件的所有元素的数组. 返回的是所有completed
属性为false
的元素组成的数组, 这个数组又重新赋值给this.todos
.
- 给相关按钮添加一个点击事件:
@click="removeCompleted"
<button class="clear-completed" v-show=" todos.length > remaining"
@click="removeCompleted">Clear completed</button>
复制代码
事项编辑
需要实现的功能为:
• 触发编辑 (双击)
• 取消编辑 (点击esc)
• 保存编辑 (回车/失去焦点)
触发编辑 (双击)
双击时进行记录正在编辑的 todo,并保存原始 todo 内容。
-
editingTodo
记录的是正在编辑的todo的内容, 因为数据是双向绑定的, 因此在调试面板中会看到它随着获取的输入编辑内容的改变而更新. -
todo.title
获取的是未改变前的title -
titleBeforeEdit
记录的是改动之前的todo的title
比如这里将 实例内容2
改成 实例内容8
, 每个部分发生的变化如下:
正在被编辑的 li 需要设置类名 editing
。
为了保证在双击之后获取的文字是当前显示的文字, 需要设置给编辑框设置v-model="todo.title"
自动获取焦点
这里直接给输入框设置autofoucs
是不行的, 因为在未双击之前输入框是隐藏的, 即使获取了焦点也看不到.
<input class="edit" v-model="todo.title" autofocus>
复制代码
所以我们需要使用自定义指令. 因为这里只有一个实例, 也不需要区分全局还是局部自定义指令了, 我们就用一个局部的作为例子:
el
指的是元素binding
是给元素传递的一些参数binding.value
是给元素传递的值, 如果这个值为true
的话就聚焦
视图中根据当前的todo是否是正在编辑的todo来判断是否聚焦:
取消编辑 (点击esc)
点击 f2 键取消编辑,还原事项内容与状态
<input class="edit" v-model="todo.title"
v-todo-focus="todo === editingTodo" @keyup.f2="cancelEdit(todo)">
复制代码
保存编辑 (回车/失去焦点)
点击回车键或失去焦点时保存编辑
- 当元素失去焦点时触发
blur
事件
注意:
当编辑内容为空时保存,应当删除 todo, 所以应该在上面的基础上增加一条判断语句:
回车会导致失去焦点(但失去焦点不会导致回车消失), 因此会出现重复删除的情况(当前事项和最后一个事项会被一起删除), 改进:
事项筛选
需要实现的功能为:
• 记录筛选类别
• 点击更改类别
在 data 中声明数据存储当前显示的事项类别,并在点击筛选按钮时更改显示的事项类别:
设置用于筛选不同类别事项的函数,并统一存储。
设置计算属性处理 todoType,并设置给视图。
设置计算属性处理 todoType,并设置给视图。
之前使用过的数据筛选函数也可以通过 filters 进行统一设置。
事项数据持久化
需要实现的功能为:获取本地存储和更新本地存储
-
localStorage 和 sessionStorage 属性允许在浏览器中存储 key/value 对的数据。
-
localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除。
-
localStorage.getItem
的返回值是一个存储对象
保存数据语法:
localStorage.setItem("key", "value");
复制代码
读取数据语法:
var lastname = localStorage.getItem("key");
复制代码
删除数据语法:
localStorage.removeItem("key");
复制代码
封装函数,用于进行本地存储数据读取。
将事项数据更改为本地存储数据。
封装本地存储的更新功能
由于多种事项操作都需要更新本地存储,单个设置十分繁琐,可以通过侦听器统一设置。
watch的书写方式(handler函数): www.jianshu.com/p/2ed125e95…
- 处理函数
handler
的第一个参数是更改为的新值, 对于对象来说,新值和旧值是一样的. handler
的参数值就等于传递给了set
// 书写方式 ()
watch: {
someValue: {
handler (newValue, oldValue) {
console.log(newValue)
}
}
}
复制代码