AngularJS中經過ngRoute來實現相關的路由功能,基本的安裝和使用請看官網.
html
ng-view這個指令和路由組合以後就能夠將$route對應的視圖放入指定的HTML中,這一過程當中它會建立本身的做用域並將模板嵌套在內部.前端
ng-view指令的優先級是1000(終極),因此AngularJS不會運行同一元素上的低優先級指令,也就是說若是一個div有ng-view指令,它上面再寫其餘指令都是沒意義的.後端
ng-view這個指令每次會建立一個新的做用域,同時移除上一個視圖及其做用域,並將新的做用域和模板關聯起來.若是路由中又相關的定義,那麼繼續將對應的控制器和當前建立的做用域聯繫起來,這些都完成後會觸發$viewContentLoaded事件.promise
視圖的刷新是在每次的$routeChangeSuccess事件以後.瀏覽器
路由一般在模塊config部分,經過$routeProvider的when和otherwise定義.
服務器
angular.module('myApp',[]).config(['$routeProvider',function($routeProvider){ $routeProvider.when('/',{ templateUrl: 'view/index.html', controller:: 'IndexController' }) .ohterwise({ redirectTo: '/' }); }]);
上面的代碼很容易理解,即便不會看意思猜都能猜出來,這裏介紹一些其餘的.when()的第二個參數是一個配置對象,一般咱們只須要配置一下templateUrl和controller就好了,有些時候咱們須要更多.
restful
(1) controller
app
它的做用是將指定的控制器與路由所建立的新做用域關聯在一塊兒,若是參數是字符串,那麼就從全部註冊過的控制器中尋找對應的內容進行關聯,若是參數是函數,那麼就會直接關聯這個函數.
ide
(2) template 和 templateUrl
函數
這兩個其實都是HTML模板,區別只是一個是String形式寫在route中,另外一個則會經過XHR讀取指定文件(或者從$templateCache).這裏面的內容都會被渲染到具備ng-view指令的DOM中.
(3) resolve
這個感受可能不是太經常使用,不過很是有用.它一般是一個對象,key-value的形式.key是注入到控制器中的依賴名稱.若是你還不明白它作了什麼,比較通俗易懂的說法就是講一個服務或者一個值在控制器加載以及$routeChangeSuccess觸發以前,被設置並注入到控制器.好比這樣:
resolve: { 'flag': ['$someService', function($someService) { if($someService.getFlag()){ return true; }else{ return false; } }]; }
上面代碼能夠看到,在flag是經過一個服務判斷後設置的,它會被注入到控制器,因此你在控制器可使用它了.補充一點就是,這裏"key-value"格式中,value能夠是服務的名字或者返回值,函數或者能夠被resolve的promise對象,它會被注入到控制器.
(4) redirectTo
這個看名字就知道幹嗎的了...不解釋
(5) reloadOnSearch
這個參數基本上你們都沒用過,由於一般都使用默認值(true).默認在$location.search()變化時會從新加載路由,若是這個參數爲false,那麼當URL查詢條件變化時就不會從新加載路由.這個功能當你使用本地分頁時對URL是更友好的.
路由裏能夠有參數,只要將when()的第一次參數寫成相似'/users/:user_id'這樣就好了,AngularJS會把它解析出來並傳遞給$routeParams.
你在從他人哦哦了人中就能夠經過$routeParams.user_id的方式獲取這個值.
通常狀況下咱們對地址欄中的URL的操做要經過window.location對象,AngularJS提供了一個服務用以解析地址欄中的URL,也就是$location.經過它你能夠訪問應用當前路徑所對應的路由,以及修改路徑和處理導航.
應用須要在內部進行跳轉時是使用$location進行的,注意的是它並無刷新整個頁面的能力.若是要刷新整個頁面可使用$window.location對象.
下面簡單介紹一下經常使用的API,推薦仍是去看官網文檔.
(1) path()
獲取以及修改當前路徑,能夠和HTML5的歷史API直接進行交互,因此前進後退按鈕能夠生效.
(2) replace()
若是但願跳轉後不能後退回去,能夠這麼寫:$location.path('/').replace()
(3) search()
獲取或者修改URL中的查詢串(也就是查詢參數),設置能夠是對象或者字符串都可.
(4) url()
和path()相似,只不過操做的是URL而不是路徑.
若是你看過官網的路由Demo,應該會發如今URL中包含#符號.之因此有這個東西是由於AngularJS一些默認狀況下的Demo都是基於路由的標籤模式.不一樣路由模式在瀏覽器地址欄中會使用不一樣的URL格式.$location默認是標籤模式.
(1) 標籤模式
標籤模式就利用內部連接的技巧,URL路徑以#符號開頭.AngularJS自己不會重寫<a>標籤,也不須要進行任何配置或者服務器支持.它的URL看起來相似這樣:http://angular.app.com/#/users
默認的AngularJS配置就是這樣的,不要任何設置.一般標籤模式是HTML5模式的一種降級方案.
(2) HTML5模式
HTML5模式就接近於咱們正常的URL,同一個地址它看起來是這樣的:http://angular.app.com/users. 在AngularJS內部,$location服務經過HTML5歷史API讓應用可以使用普通的URL路徑來訪問路由,當瀏覽器不支持HTML5歷史API時,$location服務會自動使用標籤模式的URL做爲替代 方案.在HTML5模式中,AngularJS會負責重寫<a href=""></a>中的連接.也就是說AngularJS會根據瀏覽器的能力在編譯時決定是否要重寫href=""中的連接.
後端服務器也須要支持URL重寫,服務器須要確保全部請求都返回index.html,以支持HTML5模式.這樣才能確保由AngularJS應用來處理路由.
當在HTML5模式的AngularJS中寫連接時,永遠都不要使用相對路徑.若是你的應用是在根路徑中加載的,這不會有什麼問題,但若是是在其餘路徑中,AngularJS應用就沒法正確處理路由了.
事件這個詞在前端出現的頻率真是高,根本攔不住,哪哪都是.$route服務在路由過程當中的每一個階段都會觸發不一樣的事件,能夠爲這些不一樣的路由事件設置監聽器並作出響應.
一共有4個事件用來監聽路由的狀態變化: $routeStartChange, $routeChangeSuccess, $routeChangeError, $routeUpdate.
其中最經常使用的是前兩個,這裏稍微解釋一下.
(1) $routeStartChange
看名字就能猜出來它表示的是路由開始變化的事件,在瀏覽器地址欄發生變化以前AngularJS會先廣播一下這個事件.路由會開始加載全部須要的依賴,模板和resolve部分的內容也會注入.
angular.module('myApp', []) .run(['$rootScope', '$location', function($rootScope, $location){ $rootScope.$on('$routeChangeStart', function(evt, next, current){ console.log('route begin change'); }); }]);
解釋一下事件的參數,evt是事件對象,能夠從中讀取到一些route的信息.next是將要導航到的路由,current是當前的URL.
能夠看見在這個時期咱們能夠作不少有用的事,由於此時僅僅是路由開始變化,對應的內容都還沒來得及發生改變.這裏咱們可進行permission的校驗,loading畫面的加載,對應路由信息的讀取等等.
(2) $routeChangeSuccess
在路由的全部依賴都被注入加載後,AngularJS會對外廣播路由跳轉成功的事件.
angular.module('myApp', []) .run(['$rootScope', '$location', function($rootScope, $location) { $rootScope.$on('$routeChangeSuccess', function(evt, current, previous) { console.log('route have already changed'); }); }])
這裏也稍微解釋下三個參數,evt是AngularJS事件對象,current是當前所處路由,previous是上一個路由.
剩下兩個不太經常使用的事件,你們去看官方API說明吧,這裏不介紹了.
應用場景以及可擴展性
對於SPA應用尤爲是AngularJS這種胖客戶端的應用,路由的部分一直能夠大作文章的.咱們能夠把一些頁面的基本信息配置到路由中.上面說過了when()的第二個參數是一個對象,出了AngularJS爲咱們定義好的一些屬性以外,咱們徹底能夠本身進行擴展,這些擴展出來的信息,又能夠經過注入的方式,加載到每個路由對應的控制器中.
經過這樣方式咱們就能夠解耦出來一些每一個頁面都有,可是能抽象成公共信息的這麼一類東西.好比以前我一篇博客中提到的經過路由控制頁面訪問權限,又或者每一個頁面都有一個說明當前頁面主題的title導航之類的東西,這種信息也能夠淡出抽到route中.又或者在視圖切換的間隙中,加入loading動畫均可以在路由中實現.
複雜的SPA經過路由進行視圖和視圖之間的管理和聯繫,路由的規範每每是牽一髮而動全身的.一般文件的視圖結構就映射了路由的URL結構,這些結構又在必定程度上符合restful定位資源的含義,好的路由讓你能夠更快速的尋找到對應的文件.