angularJS的兩種路由ng-router和ui-router的差別

這裏是修真院前端小課堂,每篇分享文從javascript

【背景介紹】【知識剖析】【常見問題】【解決方案】【編碼實戰】【擴展思考】【更多討論】【參考文獻】html

八個方面深度解析前端知識/技能,本篇分享的是:前端

【angularJS的兩種路由ng-router和ui-router的差別】vue

 

你們好,我是IT修真院深圳分院第07期學員,一枚正直善良的web程序員。html5

今天給你們分享一下,修真院官網 JS-06任務中可能會使用到的知識點:java

1.背景介紹
angular路由nginx

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

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

說了那麼多,那麼,什麼是路由呢?web

AngularJs中的路由,應用比較普遍,主要是容許咱們經過不一樣的url訪問不一樣的內容,可實現多視圖的單頁web應用。下面看看具體怎麼使用。

一般咱們的URL形式爲http://jtjds.cn/first/page,但在單頁web應用中angularjs經過#+標記實現,好比下面的頁面,將是下文中的路由列子:

http://192.168.1.109:8000/angular-program/src/main.html#/pagetable/page1
http://192.168.1.109:8000/angular-program/src/main.html#/pagetable/page2
http://192.168.1.109:8000/angular-program/src/main.html#/pagetable/page3

clipboard.png

當咱們點擊以上任一一個連接時,向服務器請求的地址都是http://192.168.1.109:8000/angular-program/src/main.html ,而#號以後的內容在向服務器端請求時會被瀏覽器忽略掉,因此咱們在客戶端實現#號後面的功能實現便可。簡單來講,路由經過#+標記幫助咱們區分不一樣邏輯頁面,並將其綁定到對應的控制器上。

路由介紹

 

每一個頁面均有一個控制器控制,經過路由,從而將不一樣的頁面展現出來。

二.知識剖析
ng-Route使用方法
1)引入 angular-route lib
不管是 ngRoute 仍是 ui.router ,做爲框架額外的附加功能,都必須以 模塊依賴 的形式被引入,並且要注意,須要先引用angular,這是由於angular-router.js須要傳入window.angular這個參數,這個參數只有在加載angular纔會出現。

<script src="../../bower_components/angular/angular.js"></script>
<script src="lib/angular-route.js"></script>
2)配置路由
 
var app = angular.module('ngRouteApp', ['ngRoute']);
          app.config(function($routeProvider){
    $routeProvider
        .when('/Main', {
            templateUrl: "main.html",
            controller: 'MainCtrl'
        })
        .otherwise({ redirectTo: '/tabs' });

服務與指令
ngRoute 路由模塊名
$routeProvider 服務提供者,用來定義一個路由表,即地址欄與視圖模板的映射,對應於 ui.router 中的 urlRouterProvider 和 stateProvider
$route 服務,完成路由匹配,而且提供路由相關的屬性訪問及事件,如訪問當前路由對應的 Controller,對應於下面的 $urlRouter 和 $state
$routeParams 服務,保存了地址欄中的參數,對應於下面的 $stateParams
ng-view 指令,用來在主視圖中指定加載子視圖的區域,對應於下面的 ui-view

ui-router使用方法
1)引入js文件

<script type="text/javascript" src="JS/angular.min.js"></script>
<script type="text/javascript" src="JS/angular-ui-router.min.js"></script>

2)注入ui-router模塊

var app = angular.module('myApp', ['ui.router']);
app.config(function($urlRouterProvider, $stateProvider) {
   $urlRouterProvider.otherwise("/index");  //這條是至關於報錯的時候跳轉
   $stateProvider
       .state("Main", {
           url: "/main",
           templateUrl: "main.html",
           controller: 'MainCtrl'
       })

服務與指令

ui.router 路由模塊名
$urlRouterProvider 服務提供者,用來配置路由重定向
$stateProvider 服務提供者,用來配置路由
$urlRouter 服務
$state 服務,用來顯示當前路由狀態信息,以及一些路由方法(如:跳轉)
$stateParams 服務,用來存儲路由匹配時的參數
ui-view 指令,路由模板渲染,對應的 dom 相關聯
ui-sref 指令,連接到特定狀態

三.常見問題
多視圖

多樣化視圖.jpg

 

大多數的應用程序均可以分解爲一個一個區塊。最簡單的狀況,一個應用程序有頭部(header),主體內容(main content area),以及一個尾部(footer)。
一般一個應用程序會有一個額外的側邊欄(sidebar )在頁面的左邊或者右邊。
大多數用例中,這些區塊將同時顯示在頁面上。Angular.js 的內置路由ngRoute只容許一個視圖(ng-view)出如今頁面上。

<div ng-view></div>
<div ng-view></div>

由於ng-router沒法命名ng-view,而ui-router則能夠經過命名ui-view來實現顯示不一樣的視圖出如今頁面上

//html部分
<div ui-view></div>
<div ui-view="login"></div>
                    //js部分
.state("login.page1",{
            url:"/page1",
            views:{
                '':{template:"page2"},
                'login':{template:"hello"}
            }
        })

能夠給視圖命名,如:ui-view=」status」。
能夠在路由配置中根據視圖名字(如:status),配置不一樣的模板(其實還有controller等)。

嵌套視圖
嵌套視圖:頁面某個動態變化區塊中,嵌套着另外一個能夠動態變化的區塊。

嵌入式視圖.jpg

 

其實,嵌套視圖,在html中的最終表現就像這樣:

<div ng-view>
        session
        <div ng-view>article</div>
        </div>
 
        轉成javascript,咱們會在程序裏這樣寫:
        .when('/error', {
        template: '<div ng-view>error</div>'
    })
        </code>

一運行,報了一個這樣的錯誤:

RangeError: Maximum call stack size exceeded
發現瀏覽器崩潰了,由於 ng-view 會陷入死循環,無限遞歸下去。
使用 ui.router 能很容易解決這個問題,由於它定義的路由有明確的父子關係,並經過 ui-view 指令將子路由模版插入到父路由模板的ui-view中去,從而實現視圖嵌套。看代碼:

$stateProvider
       .state("login",{
           url:"/login",
           templateUrl:"login.html"
           //controller: 'loginCtr' //選擇控制器 也能寫成 loginCtr as login
       })
       .state("login.page1",{
           url:"/page1",
           template:"page1"
       })
       .state("login.page2",{
           url:"/page2",
           template:"page2"
       })
       .state("login.page3",{
           url:"/page3",
           template:"page3"
       })

四.解決方案
須要澄清的是,這樣的要求可使用ngRoute來完成。可是你須要讓兩個控制器(一個用於列表,一個用於顯示和隱藏詳情)共享一個視圖。這樣的結果不是理想的,由於咱們想要列表和詳情頁面有各自的控制器和視圖,而且職責單一(顯示列表或者顯示列表項目的詳情)。封裝這些用戶接口模塊到它們各自的視圖,這樣咱們就有更多的「可組合UI」,容許咱們將各個區塊整合到一塊兒,或者根據需求拆分。嵌入式視圖,不只可以讓這些視圖同時出現,還能讓一個視圖嵌入到另外一個視圖中。

五.代碼實戰
六.拓展思考
單頁web應用(SPA)的簡單介紹
單頁 Web 應用 (single-page application 簡稱爲 SPA) 是一種特殊的 Web 應用。它將全部的活動侷限於一個Web頁面中,僅在該Web頁面初始化時加載相應的HTML、JavaScript 和 CSS。一旦頁面加載完成了,SPA不會由於用戶的操做而進行頁面的從新加載或跳轉。而是利用 JavaScript 動態的變換HTML的內(採用的是div切換顯示和隱藏),從而實現UI與用戶的交互。因爲避免了頁面的從新加載,SPA 能夠提供較爲流暢的用戶體驗。得益於ajax,咱們能夠實現無跳轉刷新,又多虧了瀏覽器的histroy機制,咱們用hash的變化從而能夠實現推進界面變化.

爲了單頁面應用的要求(改變視圖的同時不會向後端發出請求。),瀏覽器當前提供瞭如下兩種支持hash和history:
hash —— 即地址欄 URL 中的 # 符號(此 hash 不是密碼學裏的散列運算)。
好比這個 URL:http://www.abc.com/#/hello,hash 的值爲 #/hello。它的特色在於:hash 雖然出如今 URL 中,但不會被包括在 HTTP 請求中,對後端徹底沒有影響,所以改變 hash 不會從新加載頁面。

history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(須要特定瀏覽器支持)
這兩個方法應用於瀏覽器的歷史記錄棧,在當前已有的 back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改時,雖然改變了當前的 URL,但瀏覽器不會當即向後端發送請求。

若是不想要很醜的 hash,咱們能夠用路由的 history 模式,這種模式充分利用 history.pushState API 來完成
URL 跳轉而無須從新加載頁面。—— Vue-router 官網。
router去掉#
ui.router原理是改變location.hash的值,而location.hash 原本就是指 URL 裏 # 符號及其後的部分,若是你是要作路由映射而且不想用基於 hash 的方案,那你應該考慮 HTML5 的 History API
$location服務支持配置兩種URL格式:Hashbang模式(默認)和HTML5模式。兩種模式下的API都是通用的。

靜態網站,咱們須要修改的地方包含三個文件
index.html : ng-app的定義文件
app.js : 對應ng-app的控制文件
nginx.conf : nginx的網站配置文件

編輯 index.html,增長base標籤。
在head標籤裏增長一行

<base href="/工程名/">
編輯app.js,增長 $locationProvider.html5Mode(true)
 
book.config(['$routeProvider', '$locationProvider', '$sceProvider', 'tplProvider', function ($routeProvider, $locationProvider, $sceProvider, tplProvider) {
    $routeProvider
        .when('/', {templateUrl: tplProvider.html('welcome'), controller: 'WelcomeCtrl'})
        .when('/book', {templateUrl: tplProvider.html('book'), controller: 'BookCtrl'})             //圖書
        .when('/book-r1', {templateUrl: tplProvider.html('book-r1'), controller: 'BookR1Ctrl'})   //R的極客理想
        .when('/video', {templateUrl: tplProvider.html('video'), controller: 'VideoCtrl'})         //視頻
        .when('/about', {templateUrl: tplProvider.html('about'), controller: 'AboutCtrl'})         //關於做者
        .otherwise({redirectTo: '/'});
    $locationProvider.html5Mode(true);
}]);

編輯nginx的配置文件,增長try_files配置。

server {
        set $htdocs /www/deploy/mysite/onbook;
        listen 80;
        server_name onbook.me;
        location / {
            root $htdocs;
            try_files $uri $uri/ /工程名/index.html =404;
        }
}

七.參考文獻
AngularJs ng-route路由詳解
深究AngularJS——ui-router詳解
AngularJS中ngRouter和uiRouter的區別
多樣化視圖與嵌套視圖

八.更多討論
hash和history的好處是什麼?
一、#! #很難看,不美觀
二、微信支付接口,使用hash的話能夠忽略#後的內容,只需定義主頁的支付
三、seo優化,url#後的內容不會被收錄

什麼是路由?什麼是NG路由?
簡單來講,路由就是給指定的頁面分配一個url地址。經過這個url地址,你就能訪問到該頁面了。
好比你寫了一個頁面,/static/public/game/index.html,你的服務器項目域名http:www.dsxxx.com你經過一些方式,給該頁面配置了一個路由地址/game那麼,你就能夠經過http:www.dsxxx.com/game訪問到...,都是經過一些方式作了配置的,具體的方式你能夠隨着學習的深刻逐步瞭解到
NG路由天然是angularjs中使用的路由,天然也有vue-router,React-router等等

在路由中定義controller有什麼意義,和直接在js裏定義controller的區別是什麼?
在angularjs中controller有三種寫法
第一種

<pre name="code" class="javascript">var AppController = ['$scope', function($scope){ 
  $scope.notifyServiceOnChage = function(){ 
  console.log($scope.windowHeight); 
}; 
}]; 
app.controller('AppController',AppController);

在定義AppController的時候,先聲明方法須要注入的參數,而後再定義方法體。最後將AppController綁定到app上。

第二種

app.controller('AppController', function($scope){ 
  $scope.notifyServiceOnChage = function(){ 
   console.log($scope.windowHeight); 
 }; 
})

直接在app的controller屬性定義,首先是controller名字,而後是方法體。

第三種

function AppController($scope) { 
 $scope.notifyServiceOnChage = function(){ 
  console.log($scope.windowHeight); 
}; 
}

直接寫方法,而後在ng-controller引用該方法。

相關文章
相關標籤/搜索