序言
本章我们将使用html5的本地存储的API持久化我们的任务清单。
1. LocalStorage
localStorage是HTML5中给客户端提供了基于浏览器的存储方法。Angular中也对localStorage做了一层服务的封装,即localStorage。
Angular中的localStorage主要就两个方法去设置与获取本地存储中的值:
localStorage.setItem(key, value);
localStorage.getItem(key);
本地存储中的value只能保存字符串,如果我们需要对JSON对象进行持久化保存,则需要使用JSON.parse和JSON.stringify做序列化与反序列化的操作。
2. 改造我们的Service
我们将对我们的TaskService进行改造,增加对于本地存储的接口,用于持久化保存我们的相关任务清单。
2.1 获取与保存任务
我们对TaskService中,先添加对于JSON序列化与反序列化的代码
var STORAGE_ID = 'todos';
_getFromLocalStorage: function () {
return JSON.parse(localStorage.getItem(STORAGE_ID) || '[]');
},
_saveToLocalStorage: function (task) {
localStorage.setItem(STORAGE_ID, JSON.stringify(task));
},
然后编写get与insert方法:
2.2 获取任务列表数据
get方法只需要简单的将任务清单列表从本地存储中获取后,复制与当前的tasks数组再进行返回即可。
get: function () {
return angular.copy(service._getFromLocalStorage(), service.tasks);
},
2.3 保存任务列表数据
insert方法在插入一条新的数据后,将整个tasks数组重新覆写于本地存储。
insert: function (task) {
service.tasks.push(task);
service._saveToLocalStorage(service.tasks);
}
2.4修改对应的控制器代码
修改controller初始化的vm.tasks绑定逻辑
我们将通过TaskService的方法暴露实际的tasks数据用于外部控制器的绑定。
通过修改init方法,调整vm.tasks的赋值绑定逻辑。
function init(){
vm.status = $routeParams.status||"";
vm.statusFilter =_filterByStatus(vm.status);
vm.tasks = TaskService.get();
}
** 通过TaskService.insert的方法,操作增加任务记录**
调整后,所有对于TaskService中的tasks数组进行操作都需要通过TaskService对外暴露的接口方法而不是直接与之前一样直接操作vm.tasks或TaskService.tasks进行操作。
function addTask(){
var newTask = {
title: vm.newTask,
completed:false
};
if(!newTask.title){
return false;
}
TaskService.insert(newTask);
vm.newTask = "";
}
修改后可刷新页面查看最新的效果现在,所有新增的记录在页面刷新后还依旧会出现在浏览器中。
添加新的任务 刷新、关闭浏览器后重新打开浏览器后添加的任务依旧存在于清单上
2.5 添加删除功能
原有的删除功能,我们实在controller中进行实现的:
function removeTask(task){
vm.tasks.splice(vm.tasks.indexOf(task), 1);
}
现在我们将相关实现放置于TaskService中达到“内聚”的目的。我们通过向TaskService中添加delete方法,用于删除指定task。
delete: function (task) {
service.tasks.splice(service.tasks.indexOf(task), 1);
service._saveToLocalStorage(service.tasks);
}
最后,在调整原有controller中的方法,使用TaskService.delete方法进行删除操作。
function removeTask(task){
TaskService.delete(task);
}
2.6 编辑功能
之前我们双击任务记录后便可以对任务进行更新编辑操作,其实现逻辑也是编写在controller中且没有进行任何持久化的:
function editTask(task){
vm.editedTask = task;
}
我们同样在TaskService中增加一个put方法用于对指定索引的任务进行修改操作并进行持久化操作:
put: function (task, index) {
service.tasks[index] = task;
service._saveToLocalStorage(service.tasks);
}
原先在controller中因为是通过双向绑定达到的更新效果,所以并没有保存时间的概念。
现在我们需要额外在controller中增加一个方法用于保存当前编辑任务记录。
saveEdit方法用于获取当前task在整个tasks数组中位置,使用TaskService的put的方法去更新与持久化。
vm.saveEdit = saveEdit;
function saveEdit(task){
TaskService.put(task, vm.tasks.indexOf(task));
vm.editedTask = null;//提交后清空当前的editedTask的编辑状态
}
对应的我们也需要调整视图模板文件中的触发指令,原有编辑表单如下
<form ">
<input class="edit" ng-trim="false" ng-model="task.title" />
</form>
我们现在对表达增加两个触发持久化的动作事件:
- 按回车提交表单更新的时候
- 编辑后,鼠标离焦点击另外一条任务事件的时候也默认为提交
<form ng-submit="vm.saveEdit(task)">
<input class="edit" ng-trim="false" ng-blur="vm.saveEdit(task)" ng-model="task.title" />
</form>
我们通过在form上增加ng-submit指令与在input上增加ng-blur的指令处理我们期望的事件操作。
2.7 最终的task.service.js
抽离完了所有功能后,最终版本的task.service.js代码清单如下:
(function ()
{
'use strict';
angular
.module('todomvc')
.service('TaskService', TaskService);
TaskService.$inject = [];
function TaskService()
{
var STORAGE_ID = 'todos';
var service = {
tasks:[],
_getFromLocalStorage: function () {
return JSON.parse(localStorage.getItem(STORAGE_ID) || '[]');
},
_saveToLocalStorage: function (task) {
localStorage.setItem(STORAGE_ID, JSON.stringify(task));
},
get: function () {
return angular.copy(service._getFromLocalStorage(), service.tasks);
},
insert: function (task) {
service.tasks.push(task);
service._saveToLocalStorage(service.tasks);
},
delete: function (task) {
service.tasks.splice(service.tasks.indexOf(task), 1);
service._saveToLocalStorage(service.tasks);
},
put: function (task, index) {
service.tasks[index] = task;
service._saveToLocalStorage(service.tasks);
}
}// end of service
return service;
}//end of taskService
})();
到这里基本上所有的对于Controller业务逻辑改造全部完成了,我们将所有对于实体Task的操作全部移至TaskService中。Controller只负责与视图操作与操作TaskService提供的API达到MVC职责分离的目的,降低了功能代码的耦合性。
另外一方面,我们将所有对于tasks任务清单数组的操作的代码全部放在task.service.js中进行操作,同样提高了对于task实体功能的内聚性目的,将来所有的修改都只需要改动service中内部的实现逻辑即可,并不会去影响相关controller的代码。
Final 结束语
通过六个小章节的学习,我们基本上已经掌握了angular开发中的基础技巧与如何养成良好的编码设计习惯、分离职责提高维护性。
教程中相关的代码都可以至Github中进行浏览,https://github.com/akirapanda/angular-todo。
如对教程有任何问题欢迎留言讨论。_
网友评论