Bobril是一个由GMC Software Technology的软件架构师和开发者Boris Letocha编写的面向组件的前端框架。本文将介绍如何使用Bobril框架进行路由管理、组件定义和状态管理。
要开始使用Bobril,首先需要在计算机上安装bobril-build。请按照中的步骤进行bobril-build的安装。安装完成后,可以开始一个新的项目,或者使用bobril-build GitHub仓库中的预定义骨架simpleApp。本文将使用后者作为示例。要获取最终代码,请下载完整的示例。
Bobril提供了几种定义应用程序路由树的方法:
b.route - 定义路由URL、名称、处理器和子路由列表b.routes - 将路由注册到应用程序并调用b.initb.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。