angularJS的两种路由ng-router和ui-router的差异

大家好,我是IT修真院深圳分院第07期学员,一枚正直善良的web程序员。

今天给大家分享一下,修真院官网 JS-06任务中可能会使用到的知识点:


1.背景介绍


angular路由

AngularJS 路由允许我们通过不同的 URL 访问不同的内容。

通过 AngularJS 可以实现多视图的单页Web应用(single page web application,SPA)。

说了那么多,那么,什么是路由呢?

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

当我们点击以上任一一个链接时,向服务器请求的地址都是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的好处是什么?

1、#! #很难看,不美观
2、微信支付接口,使用hash的话可以忽略#后的内容,只需定义主页的支付
3、seo优化,url#后的内容不会被收录

什么是路由?什么是NG路由?

简单来说,路由就是给指定的页面分配一个url地址。通过这个url地址,你就能访问到该页面了。
比如你写了一个页面,/static/public/game/index.html,你的服务器项目域名http:www.dsxxx.com你通过一些方式,给该页面配置了一个路由地址/game那么,你就可以通过http:www.dsxxx.com/game访问到上面这个index.html文件了改变不同的url访问到不同的页面,都是通过一些方式做了配置的,具体的方式你可以随着学习的深入逐步了解到
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引用该方法

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容