AngularJS 路由精分

 

AngularJS 路由機制是由ngRoute模塊提供,它容許咱們將視圖分解成佈局和模板視圖,根據url變化動態的將模板視圖加載到佈局中,從而實現單頁面應用的頁面跳轉功能。html

AngularJS 路由容許咱們經過不一樣的 URL 訪問不一樣的內容。web

經過 AngularJS 能夠實現多視圖的單頁Web應用(single page web application,SPA)。promise

一般咱們的URL形式爲 http://cnblogs.com/first/page,但在單頁Web應用中 AngularJS 經過 # + 標記 實現,例如:瀏覽器

http://cnblogs.com/#/first
http://cnblogs.com/#/second
http://cnblogs.com/#/third

 當咱們點擊以上的任意一個連接時,向服務端請的地址都是同樣的 (http:/cnblogs.com/)。 由於 # 號以後的內容在向服務端請求時會被瀏覽器忽略掉。 因此咱們就須要在客戶端實現 # 號後面內容的功能實現。 AngularJS 路由 就經過 # + 標記 幫助咱們區分不一樣的邏輯頁面並將不一樣的頁面綁定到對應的控制器上。服務器

 

01app

 

路由使用

① 引入文件並注入依賴

<script src="angular-route.min.js"></script>
var app = angular.module("myApp",['ngRoute']);

② 建立一個佈局模板

之因此要建立佈局模板,是爲了告訴AngularJS應該將佈局渲染到何處。經過ng-view指令,咱們能夠精確的指定模板視圖在DOM中的渲染位置。編輯器

<div ng-app="myApp">
    <a ng-href="#/bq1">標籤1</a>
    <a ng-href="#/bq2">標籤2</a>
    <a ng-href="#/bq3">標籤3</a>
    <a ng-href="#/bq4">標籤4</a>
    <div ng-view></div>
</div>

③ 建立一些模板視圖

myBq1.htmlide

<p>這是標籤1</p>

myBq2.html函數

<p>這是標籤2</p>

myBq3.html佈局

<p>這是標籤3</p>

myBq4.html

<p>這是標籤4</p>

④ 定義路由表

app.config(['$routeProvider',function($routeProvide) {
    $routeProvide
        .when('/',{templateUrl:"home.html"})
        .when('/music',{templateUrl:"myMusic.html"})
        .when('/movie',{templateUrl:"myMovie.html"})
        .when('/novel',{templateUrl:"myNovel.html"})
        .otherwise({redirectTo:'/'});
}]);

02

 

深刻路由

① 涉及到的服務與指令

  • $routeProvider 用來定義路由表,咱們會用到裏面的when和otherwise兩個方法。
  • $routeParams 用來保存地址欄中的參數,也提供了通配某類地址的能力。
  • $location 用來分析處理url。
  • $ng-view 用來指定加載模板視圖的區域。

② $location.path()詳解

若是沒有參數,返回當前路徑,即#號後的內容;也能夠傳入字符串,將當前路徑修改成字符串的內容,並觸發路由變化。 
假設當前url:http://localhost:63342/RouteDemo/index.html#/

//返回'/'
$location.path(); 
//將當前url修改成:http://localhost:63342/RouteDemo/index.html#/music
$locaiton.path('/music'); 
//返回'/music'
$locaiton.path();

③ when及otherwise詳解

when方法可以接收兩個參數,第一個參數是路由路徑,這個路徑會與$location.path()的值進行匹配,若是沒有任何一個when方法匹配到,那麼將會執行otherwise方法。第二個參數是配置對象,它的六個屬性分別是controller,template,templateUrl,resolve,redirectTo,reloadOnSearch。

  • controller 
    該屬性值能夠是一個字符串,也能夠是一個函數。若是是字符型,則會搜索相應的控制器,若是是函數,那麼該函數表明控制器(能夠用controllerAs爲控制器命名或起別名)。控制器會與路由所建立的做用域關聯在一塊兒,而且轉到該路徑時都會執行一次控制器中的內容。
//每次路徑變爲/music觸發路由變化時都會執行一次控制器中的內容
app.config(['$routeProvider',function($routeProvide) {
    $routeProvide.when('/music'{templateUrl:"myMusic.html",controller:"myController"})           
}]);
app.controller('myController',function($scope) {
    console.log("123");
});
  • controllerAs 
    給controller屬性值表明的控制器起個別名,以便以後引用。
  • template 
    值是一個字符串,表明一個Html模板,AngularJS會拿該模板來渲染。
  • templateUrl 
    值是一個字符串,表明一個存着Html模板的路徑,AngularJS會拿該路徑下的Html模板來渲染。
  • resolve 
    值是一個對象,該對象屬性名是能夠注入到控制器的依賴,屬性值可包含下列內容。

只有當resolve對象裏全部promise對象執行完畢後纔會注入到控制器,此時纔會發生路由變化,所以能夠解決頁面閃爍問題(加載頁面後才獲取到數據去更新視圖)。咱們來看看對比,下面這個例子控制器注入的a是自定義的myService服務,注入的b則是從服務器端獲取到的數據。 
test.html代碼以下。

<p>我是測試界面 {{ name }}</p>
<div ng-repeat="name in list">{{ name }}</div>

index.html代碼以下。

<body ng-app="myApp">
    <div ng-app="myApp">
        <a ng-href="#/test">測試</a>
        <div ng-view></div>
    </div>
    <script>
        var app = angular.module("myApp",['ngRoute']);
        app.value("myService","張三");
        app.config(['$routeProvider',function($routeProvide) {
            $routeProvide
                .when('/test',{templateUrl:"test.html",
                    controller:function($scope,a,b) {
                        $scope.name = "你好"+a;
                        $scope.list = b.data;
                    },
                    resolve:{
                        a:"myService",
                        b:function($http,$timeout) {
                            var promise =  $timeout(function() {
                                return $http.get("http://localhost:3000/person");
},3000);
                            return promise;
                    }
            }});
        }]);
    </script>
</body>

若是直接在控制器而不是resolve中請求,則index.html代碼以下。

<body ng-app="myApp">
    <div ng-app="myApp">
        <a ng-href="#/test">測試</a>
        <div ng-view></div>
    </div>
    <script>
        var app = angular.module("myApp",['ngRoute']);
        app.value("myService","張三");
        app.config(['$routeProvider',function($routeProvide) {
            $routeProvide
                    .when('/test',{templateUrl:"test.html",
                    controller:function($scope,$http,$timeout,a) {
                        $scope.name = "你好"+a;
                        var promise =  $timeout(function() {
                            return $http.get("http://localhost:3000/person");
                        },3000);
                        promise.then(function(response) {
                            $scope.list = response.data;
                        });
                    },
                    resolve:{
                        a:"myService"
                    }});
        }]);
    </script>
</body>

二者效果以下,能夠看到寫在控制器中的代碼不只須要本身處理邏輯(控制器不推薦寫太複雜的邏輯)從promise的success function中取得repsonse參數,並且頁面加載不一致,服務器獲取的數據在得到後才加載,而在resolve中寫,只有等promise執行完畢後纔會跳轉,而後同步加載整個頁面。

- redirectTo 
值是一個字符串或一個函數,該屬性寫在otherwise中,表明着在when中找不到相應路徑時的重定向。若是是字符串,路徑會被替換成該值,若是是函數,它有三個參數,第一個是當前路徑的路由參數,第二個是當前路徑,第三個當前Url的查詢串,路徑會被替換成該函數的返回值,替換後都會觸發路由變化。 
- reloadOnSearch 
值是一個布爾值,爲true的時候$location.search()發生變化時就會從新加載路由,location.search是從當前URL的?號開始(包括?號)的字符串。

④ $routeParams

咱們能夠在路由參數的前面加上:號,AngularJS會把它解析出來並傳遞給$routeParams。 
  下面的例子中咱們將123456傳給value,AngularJS把其解析出來,在$routeParams中添加一個名爲value的鍵,值爲123456,咱們能夠將該服務注入到控制器中使用。 
  test.html代碼以下。

<p>我是測試界面 {{ display }}</p>
<body ng-app="myApp">
    <div ng-app="myApp">
        <a ng-href="#/test/123456">測試</a>
        <div ng-view></div>
    </div>
    <script>
        var app = angular.module("myApp",['ngRoute']);
        app.config(['$routeProvider',function($routeProvide) {
            $routeProvide
                .when('/test/:value',{templateUrl:"test.html",
                    controller:function($scope,$routeParams) {
                        $scope.display = $routeParams.value;
                }});
        }]);
    </script>
</body>

 

⑤ 路由事件

 

$route服務在路由過程當中的每一個階段都會觸發不一樣的事件,能夠爲這些事件設置監聽器並作出響應。路由事件都是系統自動從$rootScope廣播下去的,咱們最好的作法是在$rootScope中監聽,而最佳設置的地方就是run方法,能夠保證不會漏掉任何路由變化。 
  下面是四種不一樣的路由事件。

  • $routeChangeStart 
    AngularJS在路由改變以前就會廣播此事件,在廣播後,路由會開始加載路由變化所須要的全部依賴,而且模板和resolve鍵中的promise都會被resolve。
  • $routeChangeSuccess 
    在路由的依賴加載,且resolve鍵中全部promise都resolve了就會廣播此事件。
  • $routeChangeError 
    在resolve鍵中任何一個promise被拒絕或者失敗後會廣播此事件,也就是說,此事件與$routeChangeSuccess互斥。
  • $routeUpdate 在reloadOnSearch屬性設置爲false的狀況下,從新使用某個控制器的實例會廣播該事件。

相關文章
相關標籤/搜索