上一篇我们介绍了AngularJS内置的路由ngRoute,我们知道AngularJS被广泛应用于单页应用SPA(Single Page Application)中,此时路由对于我们来讲非常重要,对于内置的路由(也不能说内置,只能说在VS中默认下载的路由包是ngRoute),但是我们应该明显的知道他的不足,例如上一篇所演示,当我们通过路由导航到另外一个页面,此时若我们刷新页面,此时则会存在找不到页面的情况,此时急需我们再找一种替代方法。这就是我们本节要讲的话题【ui.router】。
说到这里,我们有必要介绍一下什么是ui.router,此UI-Router是由AngularUI团队为AngularJS构建的路由框架,它提供的改变应用视图是基于应用的状态与ngRoute路由映射不同,同时不仅仅是映射URL,相比较ngRoute,更灵活,更具扩展性。在基于ui.router的路由,我们的视图和路由不需要和URL紧紧绑定一起,我们可以在不改变URL的情况下通过ui.router来改变网站所需要呈现的内容。因为ui.router是基于路由和状态,所以同样也如ngRoute在config中进行配置。
下面我们一步步来构建如何使用ui.router,关于加入对应脚本什么的基础就不再废话。
<body ng-app="routerApp"> <div class="navbar"> <div class="navbar-inner"> <a class="brand" ui-sref="home">AnglarUi Router</a> <ul class="nav"> <li><a ui-sref="home">Home</a></li> <li><a ui-sref="about">About</a></li> </ul> </div> </div> <div class="container"> <div ui-view></div> </div> </body>
在ui.router中,我们用 ui-sref 来创建一个超链接,它会自动生成导向对应应用的状态,用 ui-view 来代替ngRoute中的ng-view。
var routerApp = angular.module('routerApp', ['ui.router']); routerApp.config(function($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise('/home'); $stateProvider .state('home', { url: '/home', templateUrl: 'partial-home.html' }) });
var routeApp = angular.module('routerApp', ['ui.router']); routeApp.config(config); function config($stateProvider,$urlRouterProvider){ $urlRouterProvider.otherwise("/home"); $stateProvider.state("home",{ url:"/home", templateUrl:"partial-home.html" }).state("about",{ }); }
<div class="jumbotron text-center"> <h1>The Home Page</h1> <p>此页面用来演示 <span class="text-danger">嵌套</span> 视图.</p> </div>
此时我们看看基本效果:
接下来我们开始进一步深入,我们开始嵌套视图页面。
此时将partial-home.html修改成如下,下面用颜色标记添加的部分。
<div class="jumbotron text-center"> <h1>The Home Page</h1> <p>此页面用来演示 <span class="text-danger">嵌套</span> 视图.</p> <a ui-sref=".list" class="btn btn-primary">List</a> <a ui-sref=".paragraph" class="btn btn-danger">Paragraph</a> </div> <div ui-view></div>
我们通过上述.list和.paragraph链接在下面ui-view中继续呈现视图,此时我们再在app.js状态中进行添加脚本。
.state('home.list', { url: '/list', templateUrl: 'partial-home-list.html', controller: function($scope) { $scope.dogs = ['普通狗', '哈士奇', '金毛']; } }) .state('home.paragraph', { url: '/paragraph', template: '你点击了paragraph' }) });
上述我们定义链接到partial-home-list.html模板,此时为如下代码:
<ul> <li ng-repeat="dog in dogs">{{ dog }}</li> </ul>
我们再来看下效果:
多视图想必我们用的地方也是更多,比如在博客园中,将最近新闻单独放在一个页面中并最终注入到母版中,每一个页面都有其控制器以及模板,这样能保证我们的一个页面整体干净而不至于内容太多而显得非常臃肿,
partail-about.html
<div class="jumbotron text-center"> <h1>The About Page</h1> <p>此页面用来演示 <span class="text-danger">多</span> 以及 <span class="text-danger">命名的</span> 视图.</p> </div> <div class="row"> <div class="col-sm-6"> <div ui-view="columnOne"></div> </div> <div class="col-sm-6"> <div ui-view="columnTwo"></div> </div> </div>
在此页面中有多个视图,一个是命名为columnOne的视图,另一个则是columnTwo视图。此时在app.js继续添加导向到此页面的状态。
.state('about', { url: '/about', views: { '': { templateUrl: 'partial-about.html' }, 'columnOne@about': { template: '我是columnOne!' }, 'columnTwo@about': { templateUrl: 'table-data.html', controller: 'scotchController' } } });
columnOne@about 和 columnTwo@about 在这里要说明一下,这里涉及到视图的相对命名和绝对命名,对于这个框架中的viewName@stateName,因为我们的主视图在我们的about状态中,此时就视图名称就演变成了columnOne@about。
以及如上scotchController对应渲染的数据:
routerApp.controller('scotchController', function($scope) { $scope.message = '品牌'; $scope.product = [ { name: '西遇', price: 50 }, { name: 'Only', price: 10000 }, { name: '杰克琼斯', price: 20000 } ]; });
模板页table-data.html
<div style="font-weight: bolder;font-size: x-large;">{{message}}</div> <table class="table table-hover"> <thead> <tr> <th>名称</th> <th>价格</th> </tr> </thead> <tbody> <tr ng-repeat="p in product"> <td>{{p.name}}</td> <td>{{p.price}}</td> </tr> </tbody> </table>
最终我们所有都已经完成,我们来整体演示下完整效果:
本节我们进一步讲了路由,关于ngRoute的替代品ui.router,在实际开发中ui.router是比较合适的替代品,就如上一篇所言中angular-resource的替代品。 下一节我们再次深入讲讲路由的高级,下节见。