使用Angular编写TodoMVC Vol 4

序言

本章将通过angular默认的ng-route组件来复用视图与前端的路由控制。

上一个章节的完成图

使用Angular编写TodoMVC Vol 4_第1张图片
Vol3 完成图

本章目的

在底部增加一个状态的过滤,可以分别显示“全部”,“未完成”和“已完成”不同状态下的清单。

1. 使用ng-route复用视图

1.1 调整index.html

首先我们先来审阅一下当年的index.html代码




    
    AngularJS • TodoMVC
    
    


body标签的section标签内的内容才是有有逻辑并且可分离的视图代码。
故我们使用ng-route来规划前端的url分发控制与对应的,通过对目标URL的撞他变化加载对应的视图与控制器文件。

1.2 分离业务视图至partials/todo.html文件

我们将index.html代码分离出来,新建一个partials/todo.html,其内容如下。
目录结构

使用Angular编写TodoMVC Vol 4_第2张图片
新建partials目录存放视图文件

消除这段代码后整个index.html就只剩下相关的入口及配置信息代码就变得干净很多。
因为使用了ng-route之后控制器的初始化就不需要我们显式的写在视图中。故我们删除掉body标签中的ng-controller属性。



最后在body标签下引入ng-route的动态视图指令ng-view


    

    
    
    
    

1.3 引入route配置信息

我们重新编辑app.js文件增加根路径的视图与控制器加载逻辑。

(function(){
    'use strict';

    angular.module('todomvc', ['ngRoute'])
        .config(routerConfig);
    routerConfig.$inject = ['$routeProvider'];


    function routerConfig($routeProvider){
        $routeProvider
        .when('/',{
            controller: 'TodoController',
            templateUrl: 'partials/todo.html',
            controllerAs: 'vm'
        })
    };
})();

routeConfig中操作$routeProvider服务,向其添加路由规则。

.when('/',{
            controller: 'TodoController', //控制器
            templateUrl: 'partials/todo.html', //视图
            controllerAs: 'vm' // 控制器As的别名语法,Angular1.2以后提倡的语法
        })

这样我们就让angular在客户端维护了一个可以根据url做出影响的前端运行时环境,这个时候我们重新在浏览器刷新地址则发现应用与之前是没区别的,唯一的区别是路径上多了一个#符号。


使用Angular编写TodoMVC Vol 4_第3张图片
多了一个#号

默认模式下,浏览器都只访问index.html的入口页 /#/之后的路径为ng-route控制的url部分,这样即使前端便可以进行无刷新的页面url的跳转操作了。

2. 向应用中添加底部状态控制栏

这次我们希望通过不同的url来显示不同的任务清单列表:

  • 在/路径下显示所有状态的任务清单
  • 在/active路径下显示所有未完成的任务清单
  • 在/completed路径下显示所有完成的任务清单

2.1 修改ng-route

添加新/:status路由,将active于completed作为参数传给controller做数据的筛选。

      .when('/:status', {
        controller: 'TodoController',
        templateUrl: 'partials/todo.html',
        controllerAs: 'vm'
      })

2.2 在controller层获取路由参数

我们在Controller层想要获取路径上的参数,则需要向Controller注入$routeParams服务,在通过$routeParams.paramName的形式便可以获取对应的参数值。
我们修改我们TodoController使其可以对不同的status状态做出不同的过滤操作。
首先,我们编写一个函数可以根据不同的status值来过滤处理controller中的任务清单数组

        function _filterDataByStatus(tasks,status){
            if (status === 'active'){
                return tasks.filter(function(task){
                    return (task.completed != true )
                }) 
            }else if(status === 'completed'){
                return tasks.filter(function(task){
                    return (task.completed == true )
                }) 
            }else{
                return tasks;
            }
        }

然后,调整TodoController中的初始化逻辑,通过$routeParam服务来获取路径中的status的值。

        function init(){

            var tasks = [
            {
                title: "第一个任务",
                completed: true
            },
            {
                title: "第二个任务",
                completed: false

            }];
            vm.status = $routeParams.status||"";
            vm.tasks = _filterDataByStatus(tasks,vm.status)
        }

我们额外声明了一个vm.status变量用于记录当前的status的值,用于模板中的底部状态过滤标签对当前激活的过滤条件做高亮显示。

2.3 增加底部的状态切换区域

我们在todo.html中增加一段新的footer标签区域用于显示底部的状态切换的状态标签按钮。


    

底部有三个按钮分别对应路径"/","/active"与"/completed"。并根据vm.status使用ng-class来高亮显示当前激活的过滤条件标签。

2.4 测试应用

我们分别测试不同状态下的清单显示情况

2.4.1 默认显示全部

使用Angular编写TodoMVC Vol 4_第4张图片
显示全部

2.4.2 待完成

使用Angular编写TodoMVC Vol 4_第5张图片
待完成

2.4.3 已完成

使用Angular编写TodoMVC Vol 4_第6张图片
已完成

2.5 问题

似乎看上去我们的过滤功能以前完成了,但是我们可以添加一个新的任务,再进行条件过滤,这个时候则会发现新建的任务清单“不见了”。
这是因为不同路由下的虽然为同名controller但是其中的实例变量还是会重新初始化。两个Controller实例没有进行数据的共享。
vm.tasks的赋值逻辑

            var tasks = [
            {
                title: "第一个任务",
                completed: true
            },
            {
                title: "第二个任务",
                completed: false

            }];

            vm.status = $routeParams.status||"";

            //此处的进行双向绑定
            vm.tasks = _filterDataByStatus(tasks,vm.status)
使用Angular编写TodoMVC Vol 4_第7张图片
不同路由下不同Controller实例中的变量不同享

在下一章的文章中我们将介绍Angular中常见几种在controller中共享、传递数据的方法并选取一种来调整我们的代码。

你可能感兴趣的:(使用Angular编写TodoMVC Vol 4)