文档章节

通过路由管理视图间切换 - AngularJS路由解析

顽Shi
 顽Shi
发布于 2014/11/21 10:50
字数 2488
阅读 2559
收藏 23

    AngularJS中通过ngRoute来实现相关的路由功能,基本的安装和使用请看官网.

    

模板的视图刷新

    ng-view这个指令和路由组合之后就可以将$route对应的视图放入指定的HTML中,这一过程中它会创建自己的作用域并将模板嵌套在内部.

    ng-view指令的优先级是1000(终极),所以AngularJS不会运行同一元素上的低优先级指令,也就是说如果一个div有ng-view指令,它上面再写其他指令都是没意义的.

    ng-view这个指令每次会创建一个新的作用域,同时移除上一个视图及其作用域,并将新的作用域和模板关联起来.如果路由中又相关的定义,那么继续将对应的控制器和当前创建的作用域联系起来,这些都完成后会触发$viewContentLoaded事件.

    视图的刷新是在每次的$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就行了,有些时候我们需要更多.

    (1) controller

    它的作用是将指定的控制器与路由所创建的新作用域关联在一起,如果参数是字符串,那么就从所有注册过的控制器中寻找对应的内容进行关联,如果参数是函数,那么就会直接关联这个函数.

    (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的控制 - $location

    一般情况下我们对地址栏中的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定位资源的含义,好的路由让你可以更快速的寻找到对应的文件.

© 著作权归作者所有

顽Shi
粉丝 275
博文 81
码字总数 92387
作品 0
普陀
程序员
私信 提问
加载中

评论(5)

梅气灶
梅气灶
最近在学习angular,在阅读route的源码,博主写的确实不错,了解的比较深入啊,学习了
顽Shi
顽Shi 博主

引用来自“成熟的毛毛虫”的评论

博主,请教下,第二次路由到相应模板页面是不是不会刷新的?

引用来自“顽Shi”的评论

没太明白你问的第二次是指什么,路由变化所引发的是视图的切换,整个页面是不会刷新的

引用来自“成熟的毛毛虫”的评论

嗯,就是这个意思,是不是有个di-href的ng属性可以强制刷新?
不是的,别人自定义的,angular原生的都是ng-*的格式,刷新视图要通过$location
沃德天拉莫帅
沃德天拉莫帅

引用来自“成熟的毛毛虫”的评论

博主,请教下,第二次路由到相应模板页面是不是不会刷新的?

引用来自“顽Shi”的评论

没太明白你问的第二次是指什么,路由变化所引发的是视图的切换,整个页面是不会刷新的
嗯,就是这个意思,是不是有个di-href的ng属性可以强制刷新?
顽Shi
顽Shi 博主

引用来自“成熟的毛毛虫”的评论

博主,请教下,第二次路由到相应模板页面是不是不会刷新的?
没太明白你问的第二次是指什么,路由变化所引发的是视图的切换,整个页面是不会刷新的
沃德天拉莫帅
沃德天拉莫帅
博主,请教下,第二次路由到相应模板页面是不是不会刷新的?
OSChina 技术专题之 AngularJS 更新版(201412)

Angular JS (Angular.JS) 是一组用来开发Web页面的框架、模板以及数据绑定和丰富UI组件。它支持整个开发进程,提供web应用的架构,无需进行手工DOM操作。 AngularJS很小,只有60K,兼容主流浏...

OSC编辑部
2014/10/17
11.2K
26
关于angular和spring集成后的路由跳转

先把我有疑问的问题描述下: angular和spring集成后,angular路由模块完成的前台路由跳转功能是否也会被spring所拦截? 最近在弄一个web app,计划是用angular来完成前端,后台用springmvc +...

Big_BoBo
2013/12/17
3.9K
6
AngularJS 如何在 HTML5 模式下通过 JS 代码切换模板

用的是 AngularJS 1.6.x,插件只有一个路由。 现在我通过另一个插件来生成视图,它在点击一个东西的时候会触发 JS 回调,这个回调跟 AngularJS 没有任何关系。 我现在想在这个回调里将页面的...

猫咪喵喵
2017/02/05
265
1
ionic入门之AngularJS扩展

ionic ionic是一个强大的混合式/hybridHTML5移动开发框架,特点是使用标准的HTML、 CSS和JavaScript,开发跨平台(目前支持:Android、iOS,计划支持:Windows Phone、Firefox OS) 的原生A...

笔阁
2015/05/04
8.4K
4
AngularJs应用页面切换优化方案

葡萄城的一款尚在研发中的产品,对外名称暂定为X项目。其中使用了已经上市的wijmo中SpreadJS产品,另外,在研发过程中整理了一些研发总结分享给大家。如本篇的在页面切换的过程中优化方案,欢...

葡萄城控件技术团队
2015/01/15
3.9K
8

没有更多内容

加载失败,请刷新页面

加载更多

Java Web 中对 ServletRequest 的一些非常规操作解决方案

1. 前言 ServletRequest 是我们搞 Java Web 经常接触的 Servlet Api 。有些时候我们要经常对其进行一些操作。这里列举一些经常的难点操作。 2. 提取 body 中的数据 前后端交互我们会在 body...

码农小胖哥
40分钟前
3
0
《Dual Encoding U-Net for Retinal Vessel Segmentation》阅读笔记-MICCAI2019

作者:Bo Wang1,2, Shuang Qiu2, and Huiguang He1,2,3 目的:Retinal Vessel Segmentation is an essential step for the early diagnosis of eye-related diseases, such as diabetes and ......

JungleKing
43分钟前
3
0
一次看懂 Https 证书认证

TLS > 传输层安全性协定 TLS(Transport Layer Security),及其前身安全套接层 SSL(Secure Sockets Layer)是一种安全协议,目的是为网际网路通信,提供安全及数据完整性保障。 如图,TLS...

极客收藏夹
57分钟前
6
0
https证书买哪家好?有哪些供应商

在选购https证书前除了要了解类型外,还需要了解https证书供应商,毕竟不同的供应商,提供的产品质量与服务也是有差异的。今天小编就为大家讲讲https证书供应商方面的内容,希望各位会喜欢。...

安信证书
59分钟前
7
0
Zuul 配置

概述:zuul底层是基于servlet,是由一系列的filter链构成。 1、路由配置 a、单例serverId映射 zuul: routes: client-a: path: /client/** serviceId: client-a 意思是...

java框架开发者
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部