C++网站开发MVC框架TreeFrog Framework教程——8.Otama模板

来源:互联网 发布:网络交友英语作文题目 编辑:程序博客网 时间:2024/05/29 16:51

C++网站开发MVC框架TreeFrog Framework教程——8.Otama模板

Otama模板系统的最大特点在于表现层的纯粹性,使用原生的HTML标签取代形如<%…%>这样的嵌入脚本代码。

使用之前,记得把配置文件(development.ini)中的模板系统设置为Otama:

TemplateSystem=Otama

Otama模板文件的后缀名是最一般的.html,区别于ERB模板的.erb,同时它把所有的逻辑代码全部转移到一个独立的文件中,它的后缀是.otm,虽然它是纯C++写的。我们可以这么理解,html文件和otm文件相结合等同于ERB系统的erb文件。
HTML文件+OTM文件
一般来说每个动作都对应有一套表现逻辑和模板文件,它们的命名分别为动作名.otm动作名.html,它们被放在“views/控制器名/”目录下。

每当你新创建了一个模板文件,记得要重新编译,因为程序运行时使用的是编译之后的共享库文件。

$ cd views$ make qmake

 

1.输出字符串

如果我们想往网页输出“Hello world”,可以对特定的标签元素添加“data-tf”属性,它的值必须是“@”开头,并且只能用字母和下划线。比如在模板文件中(.html文件)中这样写:

<p data-tf="@hello"></p>

然后在表现逻辑文件(.otm文件)中对应地有:

 @hello ~ eh("Hello world");

那么最终生成返回给用户的页面将会是这样的:

<p>Hello world</p>

波浪线(~)的意思是,用右边表达式的返回值去填充data-tf属性值为左边的网页标签,然后data-tf属性则会完全消失。而eh()方法就是返回经过HTML转义得到的字符串。

为了实现同样的效果,我们也可以这么写:

@hello ~= "Hello world"

正如ERB模板系统一样,~和eh()函数的组合可以简写为’~=’;相似地,~和echo()函数的组合也可以简写为’~==’。

但是右边不一定非得一定是字面常量,完全可以是一个普通变量甚至是一个对象实例。

 

2.Otama运算符

联系模板文件中的“标记属性”和表现逻辑代码文件中的变量的是Otama运算符,例如上面的~或者~=。
如果这一次我们选择使用另一个运算符——:,例如

@hello : eh("Hello world");

那么最终生成返回给用户的页面将变成这样:

Hello world

标签被完全移除了,因为:运算符会用右边的值完全替代拥有对应”标记属性“的网页元素。正如~和eh()可以简写为’~=’,:和eh()也可以简写为’:=’。

@hello := "Hello world"

 

3.使用控制器传过来的对象实例

正如在ERB中的那样,为了使用控制器的导出变量,我们必须先调用tfetch()或者T_FETCH()宏定义。例如,如果这个变量属于QString类型,那么我们可以这么写:

@hello : tfetch(QString, msg);  eh(msg);

正如在ERB中的那样,通过这种方式获取的变量相当于一个局部变量,注意它的作用范围——从fetch()开始到遇到一个空行。
接下来,我们来研究下如何在两个地方使用同一个导出变量。这种情况下,我们可以通过#init来实现预抓取。这样,在此之后都可以随意使用它,用法如下:

#init : tfetch(QString, msg);@foo1 := msg@foo2 ~= QString("message is ") + msg

其实还有另一种使用导出变量的方法——利用$这个特殊运算符。比如,你可以通过下面的代码直接输出导出变量的值:

@foo1 :=$ obj1

这相当于tfetch()和eh()的结合,如果想要实现tfetch()和echo()相结合,可以这么写:

@foo1 :==$ obj1

 

4.实现循环

如果我们想输出一个博客文章列表,那么必不可少地要用到循环。首先,我们要在模板文件中像这样写:

<tr data-tf="@foreach">  <td data-tf="@id"></td>  <td data-tf="@title"></td>  <td data-tf="@body"></td></tr>

然后在表现逻辑文件的内容如下:

 @foreach : tfetch(QList<Blog>, blogList);    /* Fetch processing */ for (auto &b, blogList) {     %% } @id ~= b.id() @title ~= b.title() @body ~= b.body()

其中最重要的就是%%这个符号,它指代的是整个带@foreach属性值的标签元素,比如在上面的例子中就是 <tr> 到 </tr> 。
这样,for(auto %b,blogList){}中的每一次循环都会输出一个<tr>…</tr>结构块。

 <tr>  <td>100</td>  <td>Hello</td>  <td>Hello world!</td></tr><tr>  <td>101</td>  <td>Good morning</td>  <td>This morning ...</td></tr><tr>   :    (← 不断重复)

同理,“data_tf”这个属性会消失不见。

 

5.动态增加属性

我们可以使用Otama运算符来对网页元素动态增加指定属性,例如我们有这样一个标记元素:

<span data-tf="@spancolor">Message</span>

现在,假设我们这样写表现逻辑的代码:

@spancolor + echo("class=\"c1\" title=\"foo\"");

那么,最后我们得到的页面将会是:

<span class="c1" title="foo">Message</span>

在这里,+运算符就实现了增加属性的功能。同时,我们也可以这么写:

@spancolor +== "class=\"c1\" title=\"foo\""

因为echo()等同于==,或者还可以这么写:

@spancolor +== a("class", "c1") | a("title", "foo")

这里的a()方法会创建一个带属性的HTML超链接标签,同时可以使用”|”来连接它们。但是如果你在这里使用echo()方法来代替==,那么最终的输出结果将会变成这样的字符串——key1=”val1”, key2=“val2”……。

 

6.生成超链接

举个例子,如果我们的模板文件内容如下:

<a class="c1" data-tf="@foo">Back</a>

然后,表现逻辑代码文件的内容如下:

@foo :== linkTo("Back", urla("index"))

那么,最终生成的页面代码将会是:

<a href="/Blog/index/">Back</a>

因为:运算符会完全完全替代原来的网页元素,然后linkTo(内容,连接地址)方法又会生成一个新的标签。如果你想保留原来模板中的标签的属性,而不是完全替换,可以这么写:

@foo :== linkTo("Back", urla("index"), Tf::Get, "", a("class", "c1"))

如果你不想重复写两次class=”c1”,也可以考虑使用|==运算符。它会合并前后两组属性从而生成一个新的标签,比如:

@foo  |== linkTo("Back", urla("index"))

最终生成的网页代码为:

<a class="c1" href="/Blog/index/">Back</a>

值得注意的是,如果两个地方都出现了同一个属性,那么将优先取值为表现逻辑代码的。

 

7.生成表单

使用表单进行POST数据时,最好开启CSRF(跨站请求伪造)的检查功能。生成的做法跟生成有多少相似的地方,比如我们会在模板文件这样写:

<form method="post" data-tf="@form">

然后在表现逻辑这么写:

@form |== formTag( ... )

 

8.隐藏一个网页元素

我们可以使用@dummy标记属性来隐藏一个网页元素,比如:

<div>  <p>Hello</p>  <p data-tf="@dummy">message ..</p></div>

最终生成的页面将会是:

<div>  <p>Hello</p></div>

 

9.删除标签而保留内容

有时候,你真的需要这个功能,比如布局文件已经输出了元素,然后你在模板端就不需要重复在输出,但是仍需要保留… 内部的内容,那么可以这么写:

<html data-tf="@dummytag">  <p>Hello</p></html>

最终输出结果如下:

<p>Hello</p>

 

10.导入头文件

因为表现逻辑代码是由C++写成的,所以必不可少地要导入相应的头文件。我们可以这样导入我们自己编写的头文件:

include "blog.h" include "user.h"

但是一些基础的TreeFrog框架头文件会自动导入,我们无需再多此一举。

阅读全文
0 0
原创粉丝点击