angularjs 路由机制

前言

AngularJS路由主要有内置的ngRoute和一个基于ngRoute开发的第三方路由模块ui-router,内置的ngRoute有时知足开发需求,使用ui-router能够解决不少原生ngRoute的不足。 
AngularJS的路由其实是一种纯前端的解决方案,它的本质是:当请求一个url时,根据路由配置这个url,而后再请求模板片断,并插入到ng-view中。AngularJS的路由更倾向于经过改变url进行页面的局部刷新。
javascript

 

一 ngRoute

使用ngRoute须要额外加载这个模块文件,如:html

<script src="../angular/angular.js"></script>
<script src="../angular-route/angular-route.js"></script>

同时还须要在模块声明中注入对ngRoute的依赖:前端

var app = angular.module('MyApp', ['ngRoute']);

使用ngRoute包含如下几个内容:java

名称 所属 使用
ngView directive 提供不一样路由模板插入的视图层
$routeProvider provider 提供路由配置
$route service 用于构建各个路由的url,view,controller的关系
$routeParams service 解析返回路由中带有的参数

 

$routeProvider提供了定义路由表的服务,有两个核心方法: 
1. when(path,route) 
path: string类型,表示该条路由规则所匹配的路径。 
注意: 若是路径中须要匹配参数,如path路径是:/show/:name,若是地址栏为:/show/lydia,那么这里的name以及所对应的值lydia都会保存在$routeParams服务中,须要经过$routeParams.name来获取。 
route: object类型,用来指定一系列配置项。
npm

配置 说明
controller 控制器名称
controllerAs 给控制器起个别名
template 对应路径的页面模板,会出如今ng-view处
templateUrl 对应模板的路径
resolve 该属性会以键值对对象的形式,给路由相关的控制器绑定服务或者值。而后把执行的结果值或者对应的服务引用,注入到控制器中。若是resolve中是一个promise对象,那么会等它执行成功后,才注入到控制器中,此时控制器会等待resolve中的执行结果。
redirectTo 重定向地址
reloadOnSearch 设置是否在只有地址改变时,才加载对应的模板。search和params改变都不会加载模板。默认为true,当$location.search()发生变化时会从新加载路由。
caseInsensitiveMatch 路径区分大小写

2.otherwise(params) 
对应了路径匹配不到时的状况。
promise

使用方法

第一步:添加页面 
html页面,哪里须要局部刷新,哪里就用ng-view:
app

<body ng-app="routeApp">
<div ng-view></div>


<script src="bower_components/angular/angular.js"></script>
<script src="scripts/app.js"></script>
<script src="scripts/controllers/main.js"></script>
</body>

第二步:controller添加路由配置ide

var routeApp = angular.module('routeApp',[]);
routeApp.config(['$routeProvider',function ($routeProvider) {
      $routeProvider
      .when('/list', {
        templateUrl: 'views/route/list.html',
        controller: 'RouteListCtl'
      })
      .when('/list/:id', {
          templateUrl: 'views/route/detail.html',
          controller: 'RouteDetailCtl'
      })
      .otherwise({
        redirectTo: '/list'
      });
}]);

再添加两个controller函数

routeApp.controller('RouteListCtl',function($scope) {
});
routeApp.controller('RouteDetailCtl',function($scope, $routeParams) {
    $scope.id = $routeParams.id;
});

上面这个例子只是简单的例举一下带参数和不带参数的url的路由配置和获取方法,具体的html页面和结果就不展现了。ui

resolve的用法

$routeProvider的第二个参数是路由的一些具体配置项目,这里有一个比较重要的配置,即resolve。配置resolve意味着在进入这个路由以前必须等待resolve中的数据返回,也就是说,在跳转目标路由以前先作一些额外工做去预加载数据,只有当数据准备稳当以后,才会去载入目标路由的模板和执行相应的controller。

$routeProvider
    .when("/news", {
        templateUrl: "newsView.html",
        controller: "newsController",
        resolve: {
            message: function(messageService){
                return messageService.getMessage();
        }
    }
})

在上例中,只有message有值的状况下才会去加载html页面和js。 
在路由跳转以前,会触发resolve下的全部promise,只有当全部的promise都被正确的resolve以后才会进行路由切换,此时$route会抛出$routeChangeSuccess的事件,若是没有被正确的resolve,那么$route会抛出$routeChangeError的事件,而且终止路由切换。

 

二 ui-router

ui-router相比ngRoute的优点在于,一个页面能够嵌套多个视图,,建立嵌套分层的视图,多个视图去控制某一个视图等。 
安装:

npm install angular-ui-router --save

同时在项目中引入:

<script type="text/javascript" src="app/bower_components/angular-ui-router/release/angular-ui-router.js"></script>

对应的controller中引入ui-router的依赖:

angular.module('myApp', ['ui.router']);

ui-router包含的内容与ngRoute很像,能够进行一下类比:

ngRoute ui-router
ng-view ui-view
$routeProvider $stateProvider
$routeParams $stateParams
$route $state

1.$state配置参数

参数 说明
url 默认相对路径(以^开头的是绝对路径)
views views里的每一个子视图能够包含本身的模板、控制器和预载入数据
abstract 抽象模板不能被激活
template HTML字符串或者返回HTML字符串的函数

举个例子: 
html页面:

<body>
  <div>
  <div ui-view="filters"></div>
  <div ui-view="mailbox"></div>
  <div ui-view="priority"></div>
</div>
</body>

js:

angular.module('myApp').config(['$stateProvider',function($stateProvider) {
$stateProvider
  .state('report',{
    views: {
      'filters': {
        template: '<h4>Filter inbox</h4>',
        controller: function($scope) {}
      },
      'mailbox': {
        templateUrl: 'partials/mailbox.html'
      },
      'priority': {
        template: '<h4>Priority inbox</h4>',
        resolve: {
          facebook: function() {
            return FB.messages();
          }
        }
      }
    }
  }).state('blog',{
        url:'/blog',
        views:{
            'container':{templateUrl:'templates/blog/layout.html'}
        }
    })

abstract抽象模板 
抽象模板不能被激活,可是它的子模板能够被激活。抽象模板一般用于提供一个包括了不少视图的模板,它能够传递$scope做用域给子模板,也能够在同一个url下传递自定义数据或预加载的依赖。如:

$stateProvider
  .state('admin', {
    abstract: true,
    url: '/admin',
    template: '<div ui-view></div>'
  })
  .state('admin.index', {
    url: '/index',
    template: '<h3>Admin index</h3>'
  })
  .state('admin.users', {
    url: '/users',
    template: '<ul>...</ul>'
  });

2.$stateParams 
使用$stateparams来提取在url中的不一样参数。 
若是一个url是这样的:

'/inbox/:inboxId/messages/{sorted}?from&to'

当用户访问时,请求的url是这样的:

'/inbox/123/messages/ascending?from=10&to=20'

那么$stateParams对象的值为:

{inboxId: '123', sorted: 'ascending', from: 10, to: 20}

3.$urlRouterProvider 
$urlRouterProvider和ngRoute同样,有when()和otherwise()两种用法,除此以外,还有rule()方法,能够越过任何url的匹配或者在其余路由前作路由修改,函数返回一个有效的路径的字符串。

app.config(function($urlRouterProvider){
    // 忽略url的大小写
    $urlRouterProvider.rule(function ($injector, $location) {
        var path = $location.path(), normalized = path.toLowerCase();
        if (path != normalized) 
            return normalized;
    });
})

 

路由的匹配方式

url:"/user/:id" 
url:"/user/{id}"

上面的这两个写法是同样的。

// 只会匹配 contactId 为1到8位的数字
url: "/contacts/{contactId:[0-9]{1,8}}"

能够经过?来指定参数做为查询参数,如:

url: "/contacts?myParam"     //匹配 "/contacts?myParam=value"

url: "/contacts?myParam1&myParam2"
// 匹配 "/contacts?myParam1=value1&myParam2=wowcool"
相关文章
相关标签/搜索