文章目录
  1. 1. ui-router
    1. 1.1. ui-router与ngRoute
    2. 1.2. 使用ui-router
  2. 2. 添加Sidebar组件
    1. 2.1. sidebar.template.html
    2. 2.2. sidebar.directive.ts
  3. 3. 嵌套路由
    1. 3.1. 添加路由状态
    2. 3.2. 在home.template.ts中嵌套路由视图
  4. 4. 结束语

AngularJS(v1.5.8)已经成为项目们的基本框架,《玩转Angular1》系列用于记录项目中的一些好玩或者比较特别的思路。
本文记录在angular中使用ui-router建立嵌套路由,以及路由状态相关的过程。

ui-router


ui-router与ngRoute

angular.js为我们封装好了一个路由工具ngRoute,它靠url改变去驱动视图。
angularUI也为我们封装了一个独立的路由模块ui-router,它靠状态state来驱动视图。

  • 两者区别
    • UI-Router支持嵌套视图,ngRoute不支持
    • UI-Router支持多视图,ngRoute不支持
    • UI-Router是应用程序内的一个区域,ngRoute只是应用程序中的url
    • UI-Router名称可以自定义,ngRoute名称只能是url
    • UI-Router通过名称或url导航,ngRoute只能通过url导航
    • UI-Router通过状态填充某一部件,ngRoute通过指令将填充某一部件

使用ui-router

  • 管理状态

    • 在应用程序的整个用户界面和导航中,一个状态对应于一个页面位置
    • 通过定义controller、template和view等属性,来定义指定位置的用户界面和界面行为
    • 通过嵌套的方式来解决页面中的一些重复出现的部位
  • 嵌套状态和视图

    • 当一个状态是活动状态时,其所有的父状态都将成为活跃状态
    • 状态可以相互嵌套

这里主要参考《学习 ui-router 系列文章》,后面我们会在使用到的时候再简单讲解相关的内容。

添加Sidebar组件


像其他几个框架讲解一样,我们依然使用Sidebar组件进行应用程序主界面的侧边栏。
如图:
image

这里我们在维护公用组件的时候,放置在app/shared/components文件夹里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
<ul class="nav side-menu">
<!--父菜单遍历,若href激活或者起子菜单激活则为激活状态-->
<li ng-repeat="menu in menus" ng-class="(menu.href === $state.current.name || menu.show) ? 'active' : ''" ng-click="toggleMenu(menu)">
<!--若有子菜单,则添加侧边下拉图标-->
<a><i class="fa" ng-class="menu.icon"></i> {{menu.text}} <span class="fa" ng-show="menu.childMenus && menu.childMenus.length" ng-class="menu.class ? 'fa-chevron-down' : 'fa-chevron-right'"></span></a>
<!--若有子菜单,则遍历加载-->
<ul class="nav child_menu slide" ng-click="$event.stopPropagation();" ng-show="menu.show">
<!--ui-serf-active用于匹配子元素ui-sref的href时激活class-->
<li ng-repeat="childMenu in menu.childMenus" class="slide-item" ui-sref-active="current-page">
<!--ui-sref可用于跳转-->
<a ui-sref="{{ childMenu.href }}">{{ childMenu.text }}</a>
</li>
</ul>
</li>
</ul>
...

这里我们只把关键部分进行展示,如菜单遍历、状态加载、下拉处理等等。

从代码中我们可以发现,模板中涉及两个在ui-router中比较关键的属性:

  • ui-sref用于链接跳转和激活
  • ui-sref-active用于查看当前激活状态并设置Class

  • 有三种方法来激活状态:

    • 调用$state.go()方法,这是一个高级的便利方法
    • 点击包含ui-sref指令的链接
    • 导航到与状态相关联的url

另外,我们这里使用到了$state,这个其实是从控制器传入的,属于ui-router的状态管理,下面我们会讲到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// app/shared/components/sidebar.directive.ts
export default (ngModule) => {
ngModule.directive('sidebar', ['$state', function ($state) {
return {
restrict: 'AE',
templateUrl: './shared/components/sidebar.template.html',
transclude: true,
replace: false,
link(scope, element, attrs) {
const menuShowAll = false;
scope.$state = $state;
// 初始化菜单数据
const menus = [{
icon: 'fa-home', // icon用于储存菜单对应的图标
text: '账户管理', // text用于储存该菜单显示名称
show: false,
childMenus: [{
href: 'home.accounts', // href用于设定该菜单跳转路由
text: '账户信息' // text用于储存该菜单显示名称
}, {
href: 'home.accountsadd',
text: '新建'
}]
}, {
icon: 'fa-cubes',
text: '系统管理',
show: false,
href: 'home.system'
}];
scope.menus = menus;
// 点击父菜单
scope.toggleMenu = menu => {
// 将其他菜单设置为非激活状态
scope.menus.forEach(m => m.show = false);
if (menu.childMenus && menu.childMenus.length) {
// 若当前菜单有子菜单,则切换激活状态
menu.show = !menu.show;
} else if (menu.href) {
// 若当前菜单没有子菜单,则进行跳转
$state.go(menu.href);
}
};
checkActive();
// 初始化的时候检测菜单是否激活
function checkActive() {
menus.forEach((menu: any) => {
menu.show = !!(menu.childMenus && menu.childMenus.find(item => item.href === $state.current.name));
});
}
}
};
}]);
};

在控制器中,我们主要做了以下几件事:

  • 初始化菜单数据
  • 设置一级菜单点击的事件:切换下拉/跳转
  • 初始化时检测并记载菜单状态

这里面主要用到ui-router的$state服务,该服务主要用于状态管理。

嵌套路由


该应用中,主要的嵌套路由使用,在登录后的home主界面。

添加路由状态

app.ts文件中,我们添加路由状态处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// app.ts
// ui-router路由的参数
const routerStates = [{
name: 'login',
url: '/login',
templateUrl: './modules/login/login.template.html',
controller: 'LoginCtrl'
}, {
name: 'home',
url: '/home',
templateUrl: './modules/home/home.template.html'
}, {
name: 'home.accounts',
url: '/accounts',
templateUrl: './modules/home/account/account.template.html'
}, {
name: 'home.accountsadd',
url: '/accountsadd',
templateUrl: './modules/home/account/accountAdd.template.html'
}, {
name: 'home.system',
url: '/system',
templateUrl: './modules/home/system/system.template.html'
}];

状态可以相互嵌套。有三个嵌套的方法:

  • 使用“点标记法”,例如:.state('contacts.list', {})
  • 使用parent属性,指定一个父状态的名称字符串,例如:parent: 'contacts'
  • 使用parent属性,指定一个父状态对象,例如:parent: contacts(contacts 是一个状态对象)

在home.template.ts中嵌套路由视图

子状态将把其对应的模板加载到父状态对应模板的ui-view中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--home.template.ts-->
<div class="container body">
<div class="main_container">
<!--添加Sidebar组件-->
<div sidebar></div>
<div class="right_col" role="main">
<!--嵌套路由视图-->
<div ui-view></div>
</div>
<footer>...</footer>
</div>
</div>

这样,我们就实现了路由嵌套,以及路由跳转、状态激活等功能。

结束语


这节主要简单介绍了使用ui-router代替ngRoute,并通过创建Sidebar组件以及添加路由、嵌套视图等,展示ui-router特性。
此处查看项目代码
此处查看页面效果

查看Github有更多内容噢:https://github.com/godbasin
更欢迎来被删的前端游乐场边撸猫边学前端噢

码生艰难,写文不易,给我家猪囤点猫粮了喵~

作者:被删

出处:https://godbasin.github.io

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

文章目录
  1. 1. ui-router
    1. 1.1. ui-router与ngRoute
    2. 1.2. 使用ui-router
  2. 2. 添加Sidebar组件
    1. 2.1. sidebar.template.html
    2. 2.2. sidebar.directive.ts
  3. 3. 嵌套路由
    1. 3.1. 添加路由状态
    2. 3.2. 在home.template.ts中嵌套路由视图
  4. 4. 结束语