## 路由
熟悉单页面开发的开发者,对路由并不陌生。UOkay的路由并不像其他框架的路由机制(采用hash机制),UOkay采用纯粹的软路由(完全由程序控制,并不影响路径)。为什么采用软路由?UOkay的路由并不是页面的切换,而是组件在路由视图中的切换。在无限级子组件中都可以拥有路由视图,如果采用hash机制,那么路由路径将变得十分庞大。
### 简单路由
~~~
<div id = "app">
<main></main>
</div>
~~~
~~~
let Page1 = {template: '<p>page1</p>'},
Page2 = {template: '<p>page2</p>'},
Page3 = {template: '<p>page3</p>'},
Page4 = {template: '<p>page4</p>'}
let Main = {
template: `
<div style = "display: flex;">
<div style = "flex:1" link-to="/page1">page1</div>
<div style = "flex:1" link-to="/page2">page2</div>
<div style = "flex:1" link-to="/page3">page3</div>
<div style = "flex:1" link-to="/page4">page4</div>
</div>
<route></route>
`,
routes:[{
route: [{
path: '/page1',
Component: Page1
},{
path: '/page2',
Component: Page2
},{
path: '/page3',
Component: Page3
},{
path: '/page4',
Component: Page4
}]
}]
}
var app = new Okay({
ele:'app',
components: {
main: Main
}
})
~~~
组件Main中有个匿名的路由视图route,我们在组件Main中配置路由参数routes,这里需要注意的是,我们的路由参数需要数组,因为视图中可能含有多个路由视图。我们只需要在链接DOM上加上link-to属性即可实现组件的路由。
### 命名路由
在上例中,我们设置了一个匿名路由,对于组件拥有多个路由,我们必须给路由视图进行命名以进行区别,链接DOM必须指定target属性指明该链接作用于哪个路由视图,若未指定target的,则默认指向匿名视图。当匿名路由视图不存在时,将抛出异常。
~~~
<div id = "app">
<main></main>
</div>
~~~
~~~
let Page1 = {template: '<p>page1</p>'},
Page2 = {template: '<p>page2</p>'},
Page3 = {template: '<p>page3</p>'},
Page4 = {template: '<p>page4</p>'}
let Main = {
template: `
<div style = "display: flex;">
<div style = "flex:1" link-to="/page1" target="main">page1</div>
<div style = "flex:1" link-to="/page2" target="main">page2</div>
<div style = "flex:1" link-to="/page3" target="main">page3</div>
<div style = "flex:1" link-to="/page4" target="main">page4</div>
</div>
<route name = "main"></route>
`,
routes:[{
name: "main",
route: [{
path: '/page1',
Component: Page1
},{
path: '/page2',
Component: Page2
},{
path: '/page3',
Component: Page3
},{
path: '/page4',
Component: Page4
}]
}]
}
var app = new Okay({
ele:'app',
components: {
main: Main
}
})
~~~
### 路由回调
当路由切换时,我们会调用路由切换函数,我们只需配置路由on_route
~~~
routes:[{
name: "main",
route: [{
path: '/page1',
Component: Page1,
on_route: function(src, deste, rout) {
alert('page1 show')
}
},{
path: '/page2',
Component: Page2
},{
path: '/page3',
Component: Page3
},{
path: '/page4',
Component: Page4
}]
}]
~~~
当路由视图从其他组件切换回组件Page1时,将调用on_route函数,函数的参数分别为源组件、目标组件、路由对象。
### 路由参数
我们可以直接通过路由地址设置路由参数,UOkay会对动态的将路由参数绑定到组件data.$route对象上,例如:
~~~
let Page1 = {template: '<p>page1,Hello {{$route.username}}!</p>'},
Page2 = {template: '<p>page2</p>'},
Page3 = {template: '<p>page3</p>'},
Page4 = {template: '<p>page4</p>'}
let Main = {
template: `
<div style = "display: flex;">
<div style = "flex:1" link-to="/page1/{{username}}" target = "main">page1</div>
<div style = "flex:1" link-to="/page2" target = "main">page2</div>
<div style = "flex:1" link-to="/page3" target = "main">page3</div>
<div style = "flex:1" link-to="/page4" target = "main">page4</div>
</div>
<route name = "main"></route>
`,
data() {
return {
username: '阿武阿哥'
}
},
routes:[{
name: "main",
route: [{
path: '/page1/:username',
Component: Page1,
on_route: function(src, deste, rout) {
alert('page1 show')
}
},{
path: '/page2',
Component: Page2
},{
path: '/page3',
Component: Page3
},{
path: '/page4',
Component: Page4
}]
}]
}
var app = new Okay({
ele:'app',
components: {
main: Main
}
})
~~~
### 程式化路由
UOkay除了提供模板中直接路由配置,还可以通过代码控制组件的路由,可以通过组件的okay.go方法进行路由。go函数格式:
~~~
/**
*linkto:路由地址,与页面的link-to属性规则相同
*is_new:是否新建组件
*target:路由视图
*/
go (linkto, is_new = false, target = 'default')
~~~
**需要注意的是,我们的target会递归向上寻找符合的路由视图。**也就是说我们可以在组件件中控制整个应用中符合路由路径的所有视图。
### 路由管理
UOkay路由并不是简简单单的提供组件的切换,UOkay同时提供了路由历史栈、组件回收栈。
#### 路由历史栈
UOkay提供了模拟浏览器的回退,前进等功能,这是由UOkay的历史栈管理。
![](https://box.kancloud.cn/2a7855239f3fa8d14b8e925a09937665_315x278.png)
UOkay通过路由指针进行路由的管理,我们可以通过配置link-to属性为整数,从而实现对路由指针的移动,例如:
~~~
<div link-to="-1">返回</div>
~~~
例如当上面路由被触发时,路由指针将移动一位,指向组件C,组件C将从Stop状态进入Active状态,当前的路由视图将显示在路由视图中,组件D将从Active状态中进入Stop状态。这里需要注意的是,路由指针在路由历史栈中的移动并不会销毁组件,组件将一直保存在栈中。
#### 历史栈的改变
当我们只是纯粹的移动指针时,历史栈结构并不会破坏。然而我们通过路由路径直接路由,且is_new=false时,将破坏路由栈结构,例如上图中当前路由指针指向组件D实例,当我们调用okay.go('组件C'),UOkay将会组件D,组件E,组件F弹出路由栈,进入路由回收栈,路由历史栈的结构将变成如下:
![](https://box.kancloud.cn/8b43eba5972b5bba5e9b4f6aa74710dd_310x277.png)
这里需要注意的是当采用路由路径进行路由时,路由指针将永远指向栈顶,路由指针前面的组件实例都将被弹出历史栈,即如果我们在调用okay.go(1)时,UOkay将找不到组件而出错。
#### 组件回收栈
组件在被移出历史栈并不会马上被销毁,而是会进入组件回收栈,我们可以通过设置路由配置参数设置回收栈的大小,合理的回收栈大小可以防止重复组件创建的生命周期。当应用发生路由条件时,UOkay会先搜寻历史栈,当未在历史栈中发现组件实例时,UOkay会搜寻回收栈,当在回收栈中找到组件,组件将重新被激活。回收栈大小设置如下:
~~~
routes:[{
name: "main",
recycle:true,//该路由视图是否进行回收栈机制
recyle_size: 16,//回收栈大小
route: [{
path: '/page1/:username',
Component: Page1,
on_route: function(src, deste, rout) {
alert('page1 show')
}
},{
path: '/page2',
Component: Page2
},{
path: '/page3',
Component: Page3
},{
path: '/page4',
Component: Page4
}]
}]
~~~
**回收栈满,UOkay采用的是队列先进先出的原则**