序言
本章将通过angular默认的ng-route组件来复用视图与前端的路由控制。
上一个章节的完成图
本章目的
在底部增加一个状态的过滤,可以分别显示“全部”,“未完成”和“已完成”不同状态下的清单。
1. 使用ng-route复用视图
1.1 调整index.html
首先我们先来审阅一下当年的index.html代码
AngularJS • TodoMVC
todos
-
body标签的section标签内的内容才是有有逻辑并且可分离的视图代码。
故我们使用ng-route来规划前端的url分发控制与对应的,通过对目标URL的撞他变化加载对应的视图与控制器文件。
1.2 分离业务视图至partials/todo.html文件
我们将index.html代码分离出来,新建一个partials/todo.html,其内容如下。
目录结构
todos
-
消除这段代码后整个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做出影响的前端运行时环境,这个时候我们重新在浏览器刷新地址则发现应用与之前是没区别的,唯一的区别是路径上多了一个#符号。
默认模式下,浏览器都只访问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 默认显示全部
2.4.2 待完成
2.4.3 已完成
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中常见几种在controller中共享、传递数据的方法并选取一种来调整我们的代码。