angularjs 路由機制


前言

AngularJS路由主要有內置的ngRoute和一個基於ngRoute開發的第三方路由模塊ui-router,內置的ngRoute有時滿足開發需求,使用ui-router可以解決很多原生ngRoute的不足。 
AngularJS的路由實際上是一種純前端的解決方案,它的本質是:當請求一個url時,根據路由配置這個url,然后再請求模板片段,並插入到ng-view中。AngularJS的路由更傾向於通過改變url進行頁面的局部刷新。

 

一 ngRoute

使用ngRoute需要額外加載這個模塊文件,如:

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

同時還需要在模塊聲明中注入對ngRoute的依賴:

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

使用ngRoute包含以下幾個內容:

名稱 所屬 使用
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類型,用來指定一系列配置項。

配置 說明
controller 控制器名稱
controllerAs 給控制器起個別名
template 對應路徑的頁面模板,會出現在ng-view處
templateUrl 對應模板的路徑
resolve 該屬性會以鍵值對對象的形式,給路由相關的控制器綁定服務或者值。然后把執行的結果值或者對應的服務引用,注入到控制器中。如果resolve中是一個promise對象,那么會等它執行成功后,才注入到控制器中,此時控制器會等待resolve中的執行結果。
redirectTo 重定向地址
reloadOnSearch 設置是否在只有地址改變時,才加載對應的模板。search和params改變都不會加載模板。默認為true,當$location.search()發生變化時會重新加載路由。
caseInsensitiveMatch 路徑區分大小寫

2.otherwise(params) 
對應了路徑匹配不到時的情況。

使用方法

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

<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添加路由配置

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頁面和結果就不展示了。

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"

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM