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定位资源的含义,好的路由让你能够更快速的寻找到对应的文件.