Bobril是一个由GMC Software Technology的软件架构师和开发者Boris Letocha编写的面向组件的前端框架。本文将介绍如何使用Bobril框架进行路由管理、组件定义和状态管理。
要开始使用Bobril,首先需要在计算机上安装bobril-build
。请按照中的步骤进行bobril-build
的安装。安装完成后,可以开始一个新的项目,或者使用bobril-build
GitHub仓库中的预定义骨架simpleApp
。本文将使用后者作为示例。要获取最终代码,请下载完整的示例。
Bobril提供了几种定义应用程序路由树的方法:
b.route
- 定义路由URL、名称、处理器和子路由列表b.routes
- 将路由注册到应用程序并调用b.init
b.routeDefault
- 如果当前URL中没有指定子路由,则定义默认路由
以下是一个在app.ts
中定义路由的示例:
import * as b from 'bobril';
import { mainPage } from './page';
import { pageOne } from './pages/pageOne';
import { pageTwo } from './pages/pageTwo';
b.routes(
b.route({ handler: mainPage }, [
b.route({ url: '/one', name: 'one', handler: pageOne }),
b.route({ url: '/two/:text?', name: 'two', handler: pageTwo }),
b.routeDefault({ handler: pageOne })
])
);
整个应用程序将由处理器mainPage
处理,子路由one
和two
分别在URL'/one'
和'/two'
上由处理器pageOne
和pageTwo
处理。如果没有指定子路由,将使用默认处理器pageOne
。
页面two
的URL在第二个斜杠后面包含一个参数规范。它由冒号和一个参数名称定义。问号定义参数为可选。然后可以在处理器的上下文中的ctx.data.routeParams
找到路由参数。
现在,需要定义mainPage
以渲染一些自己的内容和当前激活子路由的视觉内容。为此,将使用组件的ctx.data.activeRouteHandler
提供的函数,因此可以将page.ts
的代码更改如下:
import * as b from 'bobril';
export const mainPage = b.createComponent({
render(_ctx: b.IBobrilCtx, me: b.IBobrilNode): void {
me.children = [
tag('h1', '路由示例'),
tag('hr'),
tag('div', me.data.activeRouteHandler()),
];
}
});
这段代码将渲染一个标题、一条线和当前激活子路由的视觉内容。
现在,需要定义子页面和这些页面之间的过渡。Bobril提供了以下函数和接口用于这些目的:
b.IRouteTransition
- 过渡定义的接口(目标名称、参数等)b.createRedirectReplace
- 创建不保存历史的IRouteTransition
对象进行重定向b.createRedirectPush
- 创建保存历史的IRouteTransition
对象进行重定向b.runTransition
- 根据输入的IRouteTransition
对象运行过渡b.link
- 将输入的IBobrilNode
更改为指定名称的路由链接,并带有可选的参数
从页面one
到页面two
的重定向定义示例在pages/pageOne.ts
中:
import * as b from 'bobril';
import { textbox } from '../components/textbox';
import { button } from '../components/button';
let value = '';
export const pageOne = b.createComponent({
render(ctx: b.IBobrilCtx, me: b.IBobrilNode): void {
me.children = [
textbox({ value, onChange: (newVal) => { value = newVal; b.invalidate(ctx); } }),
button({
title: '确认',
onClick: () => {
b.runTransition(b.createRedirectPush('two', { text: value }));
return true;
}
})
];
}
});
按钮的onClick
回调创建并运行一个过渡到页面two
,定义了一个包含text
参数值的对象。
上面的过渡必须由在pages/pageTwo.ts
中定义的pageTwo
处理器处理:
import * as b from 'bobril';
import { tag } from '../helper';
import { loggedIn } from '../page';
export interface IData {
routeParams: { text?: string };
}
export interface ICtx extends b.IBobrilCtx {
data: IData;
}
export const pageTwo = b.createComponent
页面在其ctx.data.routeParams.text
中接收text
参数值,因此可以指定上下文和数据接口,并在页面组件的render
函数中使用text
。它还通过函数b.link
定义了一个到页面one
的链接节点。
有时需要管理当前页面在当前路由上是否可用,或者否可以离开当前页面。为此,可以使用IBobrilComponent
的以下静态函数:
canActivate
- 它可以通过返回false
来阻止目标处理器中的当前过渡,或者重定向到新指定的过渡canDeactivate
- 可以通过返回false
来阻止源处理器中的当前过渡,或者重定向到新指定的过渡
例如,可以通过在pages/pageOne.ts
中的页面one
组件定义中添加canDeactivate
函数定义来处理带有空textbox
值的页面离开:
canDeactivate() {
return !!value.trim() || confirm('文本框为空。确定要离开吗?');
}
或者通过在pages/pageTwo.ts
中的页面two
组件定义中添加canActivate
函数定义来处理未登录用户访问页面:
canActivate() {
if (loggedIn)
return true;
alert('未登录!');
return b.createRedirectReplace('one');
}
注意:loggedIn
变量在mainPage
中声明和设置,并导入到pageTwo
。请参阅附带的full sample
中的page.ts
。