Skip to content

Instantly share code, notes, and snippets.

@ytoney
Last active December 3, 2015 15:34
Show Gist options
  • Save ytoney/71de12bf0cd66a9a223a to your computer and use it in GitHub Desktop.
Save ytoney/71de12bf0cd66a9a223a to your computer and use it in GitHub Desktop.
AngularJS Routing Using UI-Router
使用UI-Router的AngularJS路由
AngularJS为制作单页的应用程序提供了一个强大的方式。我们在创建单页的应用程序时,路由是很重要的。我们希望我们的导航感觉像一个正常的网站,,还不使我们的网站刷新。我们已经仔细讲解过使用通常的ngRoute方法的Angular路由。
今天我们将看看使用UI-Router的路由。
概述
什么是AngularUI Router?
UI-Router是一个路由框架,它被用于AngularUI团队开发的AngularJS。这个框架提供一个与ngRoute不同的方法,这种方法改变你的应用程序视图基于应用程序的状态,而且也不只是路由URL。
States vs URL Route
使用这种方法,你的视图和路由并没有被绑定到该网站的URL上。这种方式,你可以改变你网站的部分使用路由,即使URL并没有改变。
当使用ngRoute的时,你必须要使用ngInclude或者其他的方法,这可能会让人困惑。现在你所有的状态、路由和视图都是通过你的.config()处理的,这将有助于自顶向下查看你的应用程序。
Sample Application
让我们做一些类似于其他路由教程,创建一个Home和About页面。
Setup
应用程序结构如下,填写文件。
<pre>
- index.html // will hold the main template for our app
- app.js // our angular code
- partial-about.html // about page code
- partial-home.html // home page code
- partial-home-list.html // injected into the home page
- table-data.html // re-usable table that we can place anywhere
</pre>
理解我们的应用程序结构,编写一些文件:
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<!-- CSS (load bootstrap) -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<style>
.navbar { border-radius:0; }
</style>
<!-- JS (load angular, ui-router, and our custom js file) -->
<script src="http://code.angularjs.org/1.2.13/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
<script src="app.js"></script>
</head>
<!-- apply our angular app to our site -->
<body ng-app="routerApp">
<!-- NAVIGATION -->
<nav class="navbar navbar-inverse" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" ui-sref="#">AngularUI Router</a>
</div>
<ul class="nav navbar-nav">
<li><a ui-sref="home">Home</a></li>
<li><a ui-sref="about">About</a></li>
</ul>
</nav>
<!-- MAIN CONTENT -->
<div class="container">
<!-- THIS IS WHERE WE WILL INJECT OUR CONTENT ============================== -->
<div ui-view></div>
</div>
</body>
</html>
这是我们的HTML文件。我们将使用Bootstrap框架辅助我们进行设计。请注意,我们除了载入Angular之外也加载了ui-router。UI Router从Angular核心被分离,就像ngRoute被分离一样。
用UI-Router创建链接的时候,你要使用ui-sref。通过ui-sref生成href,可以让它指向你的应用程序的某个状态。这些都是在你的app.js中被创建的。
我们也可以用<div ui-view></div>代替ngRoute的<div ng-view></div>。
现在,让我们来看下Angular应用中的app.js吧。
// app.js
var routerApp = angular.module('routerApp', ['ui.router']);
routerApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
// HOME STATES AND NESTED VIEWS ========================================
.state('home', {
url: '/home',
templateUrl: 'partial-home.html'
})
// ABOUT PAGE AND MULTIPLE NAMED VIEWS =================================
.state('about', {
// we'll get to this in a bit
});
});
现在我们已经创建了这个routerApp,它已经被应用到index.html文件中的body上了。
在app.js中我们为home和about分别创建了.state()。在home页面中,我们使用了partial-home.html模板。
让我们为partial-home.html页面添些内容,以便我们可以确切地看到内容。
<!-- partial-home.html -->
<div class="jumbotron text-center">
<h1>The Homey Page</h1>
<p>This page demonstrates <span class="text-danger">nested</span> views.</p>
</div>
现在我们就拥有自己的网站了!它不能实现很多,但是我们已经有了一个。
(demo效果图略)
在这些常规的东西完成之后,让我们看看为什么说UI-Router有一些很酷的特性吧。
嵌套视图(Home Page)
让我们看看如何嵌套视图。我们要添加两个按钮到home页,并且,在这个页面我们要根据我们点击的按钮显示不同的内容。
我们将在partial-home.html文件中添加两个按钮,然后打开Angular文件,查看我们如何改变它添加嵌套视图。
<!-- partial-home.html -->
<div class="jumbotron text-center">
<h1>The Homey Page</h1>
<p>This page demonstrates <span class="text-danger">nested</span> views.</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>
当我们要链接到一个嵌套视图的时候,要使用点标记,如:ui-sref=".list" 和ui-sref=".pargraph"。这些点标记将在Angular文件中定义,一旦我们在这里设置了它,我们将注入新的<div ui-view></div>。
在app.js文件中,让我们创建这些嵌套的状态。
// app.js
...
$stateProvider
// HOME STATES AND NESTED VIEWS ========================================
.state('home', {
url: '/home',
templateUrl: 'partial-home.html'
})
// nested list with custom controller
.state('home.list', {
url: '/list',
templateUrl: 'partial-home-list.html',
controller: function($scope) {
$scope.dogs = ['Bernese', 'Husky', 'Goldendoodle'];
}
})
// nested list with just some random string data
.state('home.paragraph', {
url: '/paragraph',
template: 'I could sure use a drink right now.'
})
...
现在,我们在home.html文件中定义的ui-sref被连接到一个实际的状态。通过创建home.list和home.paragraph,这些链接将得到提供的模板并将它注入到ui-view中。
我们需要为home页做的最后一件事是定义partial-home-list.html文件。We have also passed in a controller with a list of dogs that we will use in the template file.
<!-- partial-home-list.html -->
<ul>
<li ng-repeat="dog in dogs">{{ dog }}</li>
</ul>
现在,当我们点击list按钮时,它会将我们的dogs列表注入到模板中。或者,如果我们单击Paragraph按钮的时候,它会将我们给定的字符串注入到模板中。
你可以看到,根据state是多么容易改变应用程序的不同部分。我们不必用ngInclude、ngShow、ngHide、或者ngIf做任何形式的工作。这样可以保持我们的视图文件的简洁,因为所有的工作都是在app.js中完成的。
让我们继续,看我们如何拥有多视图。
多视图 (About Page)
在你的应用中拥有多视图是非常强大的。也许在你的网站里有一个边栏,里边有一些内容,像Popular Posts、Recent Posts、Users、或者其他任何内容。这些内容也可以被分离,注入到我们的模板中。每一个都拥有自己的controller和模板文件,所以我们的app保持简洁。
我们的应用像这样模块化也可以让我们在不同的模板中重用数据。
对于About页面,我们做两列并且每列都有自己的数据。我们首先要处理视图,然后再看我们用UI-Router如何实现this。
<!-- partial-about.html -->
<div class="jumbotron text-center">
<h1>The About Page</h1>
<p>This page demonstrates <span class="text-danger">multiple</span> and <span class="text-danger">named</span> views.</p>
</div>
<div class="row">
<!-- COLUMN ONE NAMED VIEW -->
<div class="col-sm-6">
<div ui-view="columnOne"></div>
</div>
<!-- COLUMN TWO NAMED VIEW -->
<div class="col-sm-6">
<div ui-view="columnTwo"></div>
</div>
</div>
这个文件中有两个视图,一个是columnOne,另一个是columnTwo。
为什么有人愿意用这种方式呢?这是一个很好的问题。我们是在创建一个很模块化的应用,可能会让人产生混淆吗?官方UI-Router文档里提到,有一个例子讲为什么你会有多个命名视图。在他们的例子中,展示应用的不同部分。每一部分都有它自己的数据,所以每一部分都有自己的controller和模板文件使得很容易创建像这样的东西。
到现在,我们所有的视图都被创建了,接下来让我们看看我们如何将模板文件和控制器应用到每一个视图。让我们回到app.js文件。
// app.js
...
.state('about', {
url: '/about',
views: {
// the main template will be placed here (relatively named)
'': { templateUrl: 'partial-about.html' },
// the child views will be defined here (absolutely named)
'columnOne@about': { template: 'Look I am a column!' },
// for column two, we'll define a separate controller
'columnTwo@about': {
templateUrl: 'table-data.html',
controller: 'scotchController'
}
}
});
}); // closes $routerApp.config()
// let's define the scotch controller that we call up in the about state
routerApp.controller('scotchController', function($scope) {
$scope.message = 'test';
$scope.scotches = [
{
name: 'Macallan 12',
price: 50
},
{
name: 'Chivas Regal Royal Salute',
price: 10000
},
{
name: 'Glenfiddich 1937',
price: 20000
}
];
});
...
像这样,我们的About页面就已经准备好了。现在也许还是很困惑,我们如何为about state在视图中嵌套每件事情。为什么没有为主页定义一个templateUrl,然后在一个嵌套视图对象中定义columns?这个原因就是给我们的真正伟大的工具。
相对命名和绝对命名
UI-Router分配给每一个视图一个绝对的命名。绝对命名的结构是viewName@stateName。因为我们主要的ui-view在about state里,我们就给它一个空白的名字。另外两个视图是columnOne@about和columnTwo@about。
根据命名规则, 我们在single state 中对 multiple view(多视图)进行定义。 文件对这个概念做了很好的解释,我建议浏览一下示例。功能非常强大的工具。
总结
这是一篇关于强大工具UI-Router的概述。你能用它做的事情是令人难以置信的,当你看见你的应用程序作为states而不是ngRoute的时候,Angular应用可以很容易的被创建为模块化的和可扩展的。
http://scotch.io/tutorials/javascript/angular-routing-using-ui-router
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment