一、路由:AngularJS和Ionic的异同
路由的作用,简单的概括就是基于View和Url的对应关系,处理跳转页面。
在AngularJS中,我们使用的路由功能是由模块ng-route提供的,ngRoute的思路就是最简单的路由思想,我们只需要指定每一个url对应的视图就可以了。因为ng-route现在成为一个独立的模块了,所以我们想要使用它的时候,还得去自己安装,并且在代码中显式地依赖这个模块,多少显得有些麻烦。
但是,在Ionic项目中,除了可以使用ngRoute之外,我们还可以使用一种更加强大的路由模块ui-router。并且有个好处就是,ui-router不需要我们额外引入,因为在ionic.js中就已经帮我们做了这项工作了。
二、ui-router简介
在ui-router中,有3个关键词:状态(state)、Url、模板(template),也就是说,它在ng-route的基础之上,增加了“状态”的概念。这三者是一对一的关系:每一个模板,存在于一个特定的Url,同时也对应于一个独一无二的状态。
所以,我们想要在代码中控制页面跳转的时候,既可以基于url,用href的方式进行跳转,也可以进行状态的转换,两者都可以达到切换template的目的。
三、ui-router的一般使用
假如我们现在有3个页面,模板分别为page1.html、page2.html、page3.html,同时我们分别给予一个状态:one、two、three。如果我们想要下图的跳转效果:
即1可以跳到2,2可以跳到3,3又可以跳回1。我们可以这么做:
(1)在templates文件夹下新建3个模板(为了举例,这里模板的内容很简单),其中设置一个可以跳转的按钮,按钮带有一个叫做“ui-sref”的属性,用来填入一个state:
page1.html
<ion-nav-view>
<ion-content>
<p>
This is page 1.
</p>
<!--因为要跳转到页面2,所以这里ui-sref填入页面2的状态:two-->
<a class="button" ui-sref="two">go to page2</a>
</ion-content>
</ion-nav-view>
同理,页面2和页面3:
page2.html
<ion-nav-view>
<ion-content>
<p>
This is page 2.
</p>
<a class="button" ui-sref="three">go to page3</a>
</ion-content>
</ion-nav-view>
page3.html
<ion-nav-view>
<ion-content>
<p>
This is page 3.
</p>
<a class="button" ui-sref="one">go to page1</a>
</ion-content>
</ion-nav-view
(2)在app.js中配置路由:
在config过程中配置。我们需要使用到服务
$stateProvider
它用来设置状态路由。另外,还有一个$urlRouterProvider,它通常用来设置打开App后默认跳转的Url,即启动页面。
上述例子的路由配置为:
...
.config(function ($stateProvider, $urlRouterProvider) {
// $stateProvider用来配置状态路由
$stateProvider
.state('one', { // "one"是页面1的状态
url: '/one', // "/one"是页面1的Url
templateUrl: 'templates/page1.html' // "page1.html"是页面1的模板
})
.state('two', {
url: '/two',
templateUrl: 'templates/page2.html'
})
.state('three', {
url: '/three',
templateUrl: 'templates/page3.html'
});
// 以上匹配都失败的情况下,进行下面的匹配
// 通常用在配置第一个进入的界面,比如这里定义了首先进入界面2
$urlRouterProvider.otherwise('/one');
});
这里关键是注意$stateProvider的用法。
四、ui-router路由在ion-tabs中的使用
如果应用存在ion-tab元素,那么路由的配置会复杂那么一点点。具体来说,还是我们上面的例子,假如这时候我需要把这3个页面分别对应于3个tab(即底部选项卡),那就需要考虑更多:
- 因为底部栏是3个页面中的公共部分,所以我们可以抽出来作为一个“父模板”(tabs.html),其状态为“tabs”,url为“#/tabs”
- 然后,原来的3个模板就作为它的子模板,对应的状态就得使用符号“.”连接上父状态,来设置成“tabs.one”、“tabs.two”、“tabs.three”。如此一来,对应的URL就变成了“#/tabs/one”、“#/tabs/two”、“#/tabs/three”。
Talk is cheap,还是实践一下(在尝试之前,最好了解ion-tabs控件的基本用法):
(1)创建带有3个tab的模板tabs.html,它作为3个page的“父模板”(稍后会说到),并且在每一个tab上使用ui-sref属性来建立点击的跳转:
tabs.html
<ion-tabs>
<!--ui-sref设置点击该tab跳到的对应的状态-->
<ion-tab title="1" ui-sref="tabs.one">
<!--name属性说明了装载某个模板的容器的名字,这个会在路由配置文件中体现出作用-->
<ion-nav-view name="for_template_page_1"></ion-nav-view>
</ion-tab>
<ion-tab title="2" ui-sref="tabs.two">
<ion-nav-view name="for_template_page_2"></ion-nav-view>
</ion-tab>
<ion-tab title="3" ui-sref="tabs.three">
<ion-nav-view name="for_template_page_3"></ion-nav-view>
</ion-tab>
</ion-tabs>
(2)修改app.js中的路由配置(解说在注释里):
...
$stateProvider
.state('tabs', { //父页面的状态
url: '/tabs', //父页面的Url
abstract: true, //true表示该页面作为一个父页面,父页面其实可以理解成3个子页面的共同部分,即底部的3个tab。配置之后,父页面不能单独存在。
templateUrl: 'templates/tabs.html'
})
.state('tabs.one', { //页面1的状态。注意这里不再是one,而是tabs.one,即子状态,这样的Url就会自动带上父页面的Url,即/tabs/one
url: '/one', //注意写法,这里不用带上父url,不要写成/tabs/one
views: {
'for_template_page_1': { //这里填入tab子页面的容器的名字,对应于tabs.html中<ion-nav-view>的name属性
templateUrl: 'templates/page1.html' //这里表示:在"for_template_page_1"这个tab中装载"templates/page1.html"这个模板
}
}
})
.state('tabs.two', { //其余的同上
url: '/two',
views: {
'for_template_page_2': {
templateUrl: 'templates/page2.html'
}
}
})
.state('tabs.three', {
url: '/three',
views: {
'for_template_page_3': {
templateUrl: 'templates/page3.html'
}
}
});
改写之后,路由属性嵌套得比较多,所以要写清楚。错了一个地方,通常会导致页面显示不出来。