http://blog.csdn.net/onil_chen/article/details/51758696?appinstall=0
今天好好的跟大家讲讲ionic的路由配置。
问到的朋友有点多,因为这个内容比较多,所以我一直想等我多了解一些再出关于路由的教程。
但是有些很简单的也有朋友不理解,所以我就提前出了这篇教程。
希望能对大家有点帮助,关于我遗漏的部分,后面再发教程补充吧。
但是基本的内容,简单的应用,应该这篇教程里面都会提到了。
首先我们还是从tabs类型的新建项目来学习(这个项目真的很厉害,大家可以花时间好好看看)。
我们就按照代码的启动流程开始看这个路由吧。
使用的ide是webstorm9.0.3
首先让我们运行这个项目,右键点击index.html,选择用浏览器运行,选择谷歌浏览器。
在打开的谷歌浏览器中打开开发人员工具(快捷键F12),
然后选择手机调试模式(开发人员工具栏,放大镜旁边那个按钮,可能是手机样子或者别的,版本问题,我忘记图标长什么样子了),
选择iphone6。然后刷新。重新适配界面。(只是为了比较好看而已)
既然这节课是说路由,那最开始我们最先要关注的就是
http://localhost:63342/routeDemo/www/index.html#/tab/dash
为什么会访问这个地址呢?#tab/dash这个就是路由,但是为什么访问的是这个路由,又是什么意思,怎么定义的呢?
首先我们做一个操作,在地址栏里面访问http://localhost:63342/routeDemo/www/就是去掉了index.html#/tab/dash这不部分的内容。
访问之后,你会发现,就算是只访问http://localhost:63342/routeDemo/www/最后访问的还是http://localhost:63342/routeDemo/www/index.html#/tab/dash
这里有两个知识点,一个是web的,当url访问的是网站的某个文件夹时,浏览器会自动打开该文件夹下的index.html文件。
即打开的就是上面这个代码,代码是按照顺序从上到下解析的。跑到body的ng-app=“starter”,就是自动启动应用的脚本。
就会在模块池(我随意说的,便于理解)查找名字叫做starter的模块。是的,模块,没有应用,你没有看错。
纸上得来终觉浅,绝知此事要读源码(read the fucking source code)
我们打开app.js查看源码
可以看到这里定义了名字叫做starter的模块,前面自动启动的就是它,后面中括号里面的内容,可以理解为这个模块的依赖,就是说这个模块要运行起来,是要在这三个模块运行起来的基础上才行的,这么说不是很严谨,但是新手这么理解是可以的。
一般在项目中,会把这个模块的返回值保存下来,这样在代码中操作会比较方便。
var app = angular.module(name,[])这样子的形式,在代码中直接使用app就是当前这个应用了,比较方便。
恩,我们接着往下看
注意看前面的.run()可以这么理解在app运行的时候执行的内容,看内容这一块是打包之后才有用的。所以你的项目只是一个单存的web项目,可以把这个删除了也没有关系。
这个.run()还可以用来引入rootscope,全局的控制器上下文,可以实现一些简单的数据传递,或者通用函数的统一处理。写法如下
.run(function($rootScope){ $rootScope.debug = true;})这样子你在子控制器里面引入$rootScope,就能获得这个全局变量了,比如在是否打印log的时候可以这么实现
$rootScope.debug && console.log("运行日志")
这里还要注意的是.run()是直接接在angular.module(name,[]).run()注意这是一个链式的写法。有语句后面加分号编程习惯的小伙伴,可以注意一下,按照上面提到的,可以把这个拆开写var app = angular.module(name,[]); 这是可以断开的app.run(); 这样子的写法有个好处就是,这两部分的内容可以写到不同的文件里面。有些人喜欢把route这部分的内容分离,就是可以这么实现的。
还是接着看源码
.config()可以理解为应用运行的配置文件,可以用来定义一些基础的配置,这里引入的是$stateProvider,用来配置路由。第二个参数其实是可以不用的。但是这里是用来定义,当你访问链接的时候没有携带任何的路由信息,那系统会自动访问otherwise配置的路由。就像我们一开始访问的地址http://localhost:63342/routeDemo/www/。浏览器自动帮我们补齐了地址http://localhost:63342/routeDemo/www/index.html。这是一个没有路由信息的地址,所以这里配置的otherwise就会帮我们自动补上#/tab/dash。这里就解释了为什么我们直接访问项目目录,会访问http://localhost:63342/routeDemo/www/index.html#/tab/dash。
接下来,我们来看一个详细的路由配置。这里有两种情况。是否为母版(模板).
我们看tab的这个路由,url就是路由地址,abstract:true就是指设置这个界面为母版界面,可以这么理解,这是一个架子,所有的子界面都有这个统一的界面。
templateUrl是定义了这个路由视图对应的界面。这里我们还是围绕着http://localhost:63342/routeDemo/www/index.html#/tab/dash。这个链接。我们要解释里面的这个tab是什么。
这里我们做一个有意思的尝试,我们注销掉路由配置里面的$urlRouterProvider.otherwise('/tab/dash')防止我们输入错误路由的时候,系统自动跳转。然后我们在浏览器里面访问http://localhost:63342/routeDemo/www/index.html#/tab只访问到tab这一级。(注意在浏览器中只修改路由是不会重新加载页面的,这也是路由的一个优点,所以要刷新页面之后在修改路由,这样我们刚才修改的代码才会有效)
然后我们会在界面上看到两个浅浅的框框。
要仔细看,不然会以为没有东西。我们在从控制台看一下html
注意看这个视图是有解析的。恩,这 暂且放一边不看,我们接着看另外一个路由配置
首先是这个路由的名字tab.dash这里的点和js中的点一样理解为对象的属性,这里表示一种从属关系。指dash这个视图是tab的一个子视图。
这个路由配置和tab的路由配置有个明显不同的地方就是多了一个views,可以简单理解为用来定义视图详情。格式是views:{name:{parms}}
这里最应该关注的就是‘tab-dash’这个视图名字。首先要指导这个视图名字是从哪来的,又是什么意思?
我们打开tabs.html文件
可以看到在tabs地下定义的tab里面有一个ion-nav-view 它的名字定义为‘tab-dash’这个意思就是。tab.dash这个路由定义了,这个路由的视图是在‘tab-dash’这个tab的视图里面绘制的。
这个ion-nav-view我们在index.html中也有见过<ion-nav-view ></ion-nav-view>。那这里要怎么理解呢?
我们对代码做一点小改动。改动tab的配置。加入views属性。
然后给index.html中的<ion-nav-view ></ion-nav-view>加入属性name='main'。
然后运行项目,项目运行成功。给每一个视图定义了名字之后,理解起来就容易很多了。下面我画一个简单的图来说明这几个关系。
这里我把视图之间画的比较开,便于理解。但是这些视图之间的关系,要以我下面的说明为主。
首先我们来理解系统默认的那种没有定义views属性的路由,它们会被默认绘制在最上层的main视图里面。从上往下,第一个没有定义名字的view。
比如我们在项目中常常会有一些界面不需要下面的tab切换。所以我们可以把他们定义为不带views属性的,即不声明所属视图的路由,他们都会被绘制在main视图中,他们和tabs视图是同级的关系。这个视图是直接在主视图中绘制的,所以图中蓝色的tabs视图,实际上是不存在的。
tabs视图下面有定义了很多个子视图,根据代码控制这些子视图是只能同时有一个是显示的,其他的子视图都会被放入视图缓存中。所以途中紫色的视图,应该是和tabs视图一样的的,但是它们是存在的。当这些视图的大小都完全一样的时候,那我们看起来就像只有一个视图了。这里我在画一个简化版的tabs切换的视图关系,便于理解。
正视图侧视图
根据上面这两个不同角度的图应该能够理解tabs是怎么做到切换的了。我们能够看到的就是最上层的,所以在tabs母版里面定义的tabs切换栏,在每一个子视图里面都有,就是这么实现的。
所以说视图要不要定义,要怎么定义可以根据项目需要灵活的选择。定义在同一个视图地下的路由在切换的时候,会有历史保留,可以直接使用back按钮,进行返回操作。但是游离在子视图,即没有设置views的视图,相互之间是没有历史的,他们之间的返回需要手动的补充功能,我觉得应该是我哪里使用的不对。但是还没定位出来。
看完了新建项目中定义的这几个属性,我们接下来来看几个,比较常用的新建项目中没有提到的属性。
1、template
这个属性和templateUrl都是用来定义视图对应的html模板的,前者接受的是一个html的字符串,后者接受的是一个文件路径的地址。比较好理解。
2、prefetchTemplate
默认为true。这个设置为false,表示不提前加载html,模板。这里我们看一下新建项目的日志
这里我们在启动项目的时候,走过路由配置,所有的html都会被预加载到缓存中。是的后面的视图之间的切换会很流畅。
但是也有一个问题,就是启动项目的时候,要加载过多的文件,有些文件还不一定有用,在很多级下面的文件,很少使用到。
所以可以选择,把一些不常用的视图设置为false,这样一开始就不会去加载它们了。
在做按需加载的时候。也可以把这个值设置为false。js文件都按需加载了,访问首页只加载了一个js文件却加载了几十个上百个的html文件,这很不科学。
3、resolve:预载入
使用预载入功能,可以预先载入一系列依赖或者数据,然后注入到控制器中。
在路由中的resolve,能够保证在路由到达前载入数据保证(promises).
预载入对象需要一个对象,这个对象的key纪要注入到控制器的依赖,这个对象的值为需要被载入的服务。
如果传入的是字符串,路由会视图匹配已经注册的服务。
如果传入的是函数,该函数会被注入,并且该函数返回的值便是控制器的依赖之一。
如果该函数返回一个数据保证(promise),这个数据保证将在控制器被实例化前被预先载入并且数据会被注入到控制器中。
这个用来实现按需加载的基础,也有其他的模块依赖,或者前置函数的执行,都是靠它来完成的。
接下来还要讲到的几个常用事件。
1、$ionicView.enter
在进入视图的时候响应的事件,在控制器中使用on方法监听触发
2、$ionicView.leave
在离开视图的时候响应的事件。注意如果从A界面到B界面跳转,那么B界面的enter会先响应,再响应A界面的leave事件
3、$stateChangeStart
在切换路由是响应的事件,可以用来判断前置路由是什么,控制当进入某些页面时执行的函数,比如说进入某些页面都要把右上角的按钮显示出来等等
暂时能想起来的,就这么多,其中需要明确关注的是resolve这个属性。后续的深入学习,对它的涉及会比较多。
这节课没有demo,直接新建一个tabs类型的项目跟着看就可以了。
大家还有其他的问题可以通过以下方式找到我