一.背景介绍
angular路由
路由(route),几乎所有的MVC(VM)框架都应该具有的特性,因为它是前端构建单页面应用(SPA)必不可少的组成部分。
那么,对于angular而言,它自然也有内置的路由模块:叫做ngRoute。
不过,大家很少用它,因为它的功能太有限,往往不能满足开发需求!!
一个基于ngRoute开发的第三方路由模块,叫做ui.router,受到了大家的“追捧”。
ngRoute vs ui.router
首先,无论是使用哪种路由,作为框架额外的附加功能,它们都将以模块依赖的形式被引入,简而言之就是:在引入路由源文件之后,你的代码应该这样写(以ui.router为例):angular.module("myApp", ["ui.router"]); // myApp为自定义模块,依赖第三方路由模块ui.router
这样做的目的是:在程序启动(Angular)的时候,加载依赖模块(如:ui.router),将所有挂载在该模块的服务(provider),指令(directive),过滤器(filter)等都进行注册,那么在后面的程序中便可以调用了。
说到这里,就得看看ngRoute模块和ui.router模块各自都提供了哪些服务,哪些指令?
二.知识剖析
ngRoute
$routeProvider(服务提供者) ——— 对应于下面的urlRouterProvider和stateProvider
$route(服务) ——— 对应于下面的urlRouter和state
$routeParams(服务) ——— 对应于下面的stateParams
ng-view(指令) ——— 对应于下面的ui-view
ui.router
$urlRouterProvider(服务提供者) ——— 用来配置路由重定向
$urlRouter(服务)
$stateProvider(服务提供者) ——— 用来配置路由
$state(服务) ——— 用来显示当前路由状态信息,以及一些路由方法(如:跳转)
$stateParams(服务) ——— 用来存储路由匹配时的参数
ui-view(指令) ——— 路由模板渲染,对应的dom相关联
ui-sref(指令)
(注:服务提供者:用来提供服务实例和配置服务。)
这样一看,其实ui.router和ngRoute大体的设计思路,对应的模块划分都是一致的(毕竟是同一个团队开发),不同的地方在于功能点的实现和增强。
那么问题来了:ngRoute弱在哪些方面,ui.router怎么弥补了这些方面?
这里,列举两个最重要的方面来说(其他细节,后面再说):
多视图
嵌套视图
<!-- 一个页面只能有一个ng-app,定义应用 -->
<body ng-app='helloworld'>
<!-- ui-sref——————是一个指令,引用一个状态 -->
<!-- 添加一些ui-sref链接 点击后,链接将激活一个状态。 -->
<!-- ui-sref-active—————— 查看当前激活状态并设置 Class -->
<a ui-sref='hello' ui-sref-active='active'>Hello</a>
<a ui-sref='about' ui-sref-active='active'>About</a>
<!-- 展示——————视口 -->
<!-- 当状态(statue)被激活(active)时,状态的视图template:将被加载到视口中。 -->
<div ui-view></div>
<!-- 引入顺序:angular、ui-router、自己的js文件 -->
<script src='angular-1.5.8.js'></script>
<script src='angular-ui-router.js'></script><script src='test.js'></script>
</body>
创建一个Angular模块(注册模块的过程)————myApp(是主要模块),并依赖注入ui.router模块
第一个是模板名(即应用名ng-app),第二个是依赖注入列表(数组)
需要注意的是这里的是 ui.router,而不是 ui-router
注册模板的方式有两种,第一种如下,这种方法注册的模板,
angularjs机制会新建一个模板,归根结底是不同的模版
var myApp = angular.module('helloworld' , ['ui.router']);
第二种是: var myApp = angular.module("helloworld");
如果应用程序中有了这个模板,那么就返回这个模板一样配置的模板,要注意的是,他们是同一个模板
实例化的模块有一个config的方法,通过它可以在模块跑起来之前做一些配置性工作,路由设置什么的就是在config中完成的。
config支持依赖注入(例如下面注入了$statueProvider),但是只有provider和constants是可以被注入进去的,其他的不可以。
//还可以把 $locationProvider也注入进来,逗号分隔
// 把 $locationProvider加进来的目的主要是希望在高级浏览器上是以html5Mode更改URL,
// 并且针对于IE8 9 这样的不支持的设置hashPrefix为“!”(默认html5Mode是false hashPrefix是'')。
//$urlRouterProvider这个是在没有匹配路由时,跳转默认路径
myApp.config(function($stateProvider,$urlRouterProvider){}
//配置路由状态的另一种写法
//myApp.config(['$stateProvider',function($stateProvider){
// ......
//}]);
//config方法 固定写法就是 app.config(function(){...})
//AngularJS模块可以在被加载和执行之前对模块自身进行配置。
//当你需要在AngularJS模块加载之前进行配置,就要用到config。
//只有提供者(Provider)和常量(constant)才能注入到config中。
//$statueProvider在配置块中注册了两个状态
//状态是UI路由器应用程序的基本构建块。这个javascript对象是一个简单的状态定义。
var helloState = {
//name和url并没有必须相同这一说法,是不同的两个东西
//这里的name对应的是ui-sref里的东西
name:'hello',
//当状态为活动状态时,浏览器的网址将会是/hello。
url:'/hello',
//该template:字符串定义状态的视图。当状态为活动状态时,此视图将被加载到视口中。
//还可以使用templateUrl,对应的值是html片段,例如:templateUrl:'artical.html'
template:'<h3>hello world!</h3>'
};
var aboutState = {
name:'about',
url:'/about',
template:'<h3>ITs the UI-Router hello world app!</h3>'
};
$urlRouterProvider.otherwise('/hello');
$stateProvider.state(helloState);
$stateProvider.state(aboutState);
});
/*另一种写法就是:
var myApp = angular.module('helloworld' , ['ui.router']);
myApp.config(function($stateProvider){
$stateProvider
//.state里的第一个参数对应ui-sref
.state('hello',{
url:'/hello',
template:'<h3>hello world!</h3>'
})
.state('about',{
url:'/about',
template:'<h3>ITs the UI-Router hello world app!</h3>'
})
//一个子路由且需要传递参数的例子:
//state可以嵌套,state名必须唯一,通过state名中的点来划分Parent/child层次。
//格式为:父View.子View
//下面的例子是 hello.son, 前提是
//hello里的 template里要有<a ui-sref='...'>...</a>和<ui-view></ui-view>
.state('hello.son',{
// ?后边接传递的参数,如果参数有多个,用 & 连接
url:'/list?page&type',
// params 开始以为是用来传参的,然而。。。
//params是在目标界面定义要接受的参数
params:{'page':null,'type':null},
//params 和 data之间的区别:
//定义在 parent state 上的 data,child state 可以继承
//params的作用是定义一个 state 的子路由,但不反应在 URL 中,
//需要在调用的时候传入 {param: xxx} 来访问
//因此,data 是用于在父子路由间传输数据,
//而 params 是定义子路由的访问方式。两者的用处是有本质不同的
//还可以为路由定义控制器
controller:'someThing',
//如果还要嵌套子路由的话,继续用.连接,然后继续在template中加a标签和ui-view
template:'<h1>Good job!</h1>'
})
});
*/
/*
var myApp = angular.module("myApp", ['ui.router','oc.lazyLoad']);
myApp.config(function ($stateProvider, $urlRouterProvider) {
//懒加载
var _lazyLoad = function (loaded) {
return function ($ocLazyLoad) {
return $ocLazyLoad.load(loaded, {serie: true});
}};
三.常见问题
多视图
多视图:页面可以显示多个动态变化的不同区块
四.解决方案
参数:
name:状态的名称。
stateConfig:状态配置对象。配置具有以下各项属性:
template: string/function,html模板字符串,或者一个返回html模板字符串的函数。
templateUrl:string/function,模板路径的字符串,或者返回模板路径字符串的函数。
templateProvider:function,返回html模板字符串或模板路径的服务。
controller:string/function,新注册一个控制器函数或者一个已注册的控制器的名称字符串。
controllerProvider:function,返回控制器或者控制器名称的服务
controllerAs:string,控制器别名。
parent:string/object,手动指定该状态的父级。
resolve:object,将会被注入controller去执行的函数,string,function>形式。
url:string,当前状态的对应url。
views:object,视图展示的配置。string,object>形式。
abstract:boolean,一个永远不会被激活的抽象的状态,但可以给其子级提供特性的继承。默认是true。
onEnter:function,当进入一个状态后的回调函数。
onExit:function,当退出一个状态后的回调函数。
reloadOnSearch:boolean,如果为false,那么当一个search/query参数改变时不会触发相同的状态,用于当你修改$location.search()的时候不想重新加载页面。默认为true。
data:object,任意对象数据,用于自定义配置。继承父级状态的data属性。换句话说,通过原型继承可以达到添加一个data数据从而整个树结构都能获取到。
params:url里的参数值,通过它可以实现页面间的参数传递。
五.代码实战
六.拓展思考
路由怎么传参
七.参考文献
八.更多讨论
ui-router路由配置时用 $stateProvider 和$urlRouterProvider。
ngRoute是官方路由。
ui-route是第三方路由。
ngroute是用AngularJS框架的核心部分。
ui-router是一个社区库,它是用来提高完善ngroute路由功能的。
ui-router允许嵌套视图(nested views)和多个命名视图(multiple named views)。
Q2:ui-router的优点有哪些?
A2:
1、UI-Router支持嵌套视图,ngRoute不支持
2、UI-Router支持多视图,ngRoute不支持
Q3:一般ui-router传参传递什么参数?
A4:使用url传参或者params对象传参。