美文网首页程序员我爱编程
使用Angular编写TodoMVC Vol 6

使用Angular编写TodoMVC Vol 6

作者: AkiraPan | 来源:发表于2016-06-13 15:50 被阅读199次

    序言

    本章我们将使用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>
    

    我们现在对表达增加两个触发持久化的动作事件:

    1. 按回车提交表单更新的时候
    2. 编辑后,鼠标离焦点击另外一条任务事件的时候也默认为提交
    <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
    如对教程有任何问题欢迎留言讨论。_

    相关文章

      网友评论

        本文标题:使用Angular编写TodoMVC Vol 6

        本文链接:https://www.haomeiwen.com/subject/pdyydttx.html