您的位置:首页 > 产品设计 > UI/UE

Part I. 设计人员指南 Designer's Guide -- Chapter 1. 快速入门 Quick Start -- (一)

2007-07-27 21:04 585 查看

Part I.  设计人员指南 Designer's Guide

Chapter 1.  快速入门 Quick Start

模版 + 数据模型 = 输出 Template + data model = output 

FreeMarker是基于这样一个理念的:设计人员与开发人员是不同的人,他们分别擅长不同的技能。理想情况下,应该将设计人员的关注点集中到外观展现上 – 他们创建HTML文件、图片、和web页面的其他方面。同时,开发人员来创建产生数据的系统,再由设计人员设计的页面来显示。

问题是你经常不得不在页面上(或其他文档中)显示一些在设计期未知的信息。一个典型的电子商务应用就是基于这种动态数据的 – 比如库存的实时状态,美元与日元的转换汇率,顾客的订单是否已经发送等。这些数据总是在变。遇到这种情况,你需要再你的HTML(或其他文本中放一些特殊的结构;FreeMarker的输出不仅仅限于HTML),然后FreeMarker会在需要输出页面给用户时将这些代码替换成正确的数据。现在以一个非常简单的例子开始 -- 你需要在欢迎页面显示用户的名称并提示你公司的最近产品:

<html>

<head>

  <title>Welcome!</title>

</head>

<body>

  <h1>Welcome ${user}!</h1>

  <p>Our latest product:

  <a href="${latestProduct.url}">${latestProduct.name}</a>!

</body>

</html> 

上面的内容就是一个普通的HTML片段(除了其中的特殊代码${...})。这些代码是FreeMarker要发送输出到用户时,用来说明应该将实时的文本信息放到哪里去的。像这样的文件被叫做模版templates

那么是user, latestProduct.url和latestProduct.nam从哪儿来的呢?他们是从数据模型中复制来的。数据模型是存储在计算机内存中的内容。由开发人员写的程序创建数据模型(即数据模型由程序动态生成),这就是模版提供变化信息的机制。这些信息可能来自数据库、文件甚至是由程序生成的内容都可以。但模版作者其实并不关系数据来源。他们只是使用已有的数据模型。

我们说,输出是通过将模版和数据模型相结合创建的:

Template + data model = output

数据模型可能是这样:

(root)

  |

  +- user = "Big Joe"

  |

  +- latestProduct

      |

      +- url = "products/greenmouse.html"

      |

      +- name = "green mouse" 

(不要误会:数据模型并不是文本,这里只是提供一个数据模型的形象的样子)

打个比方,这就像是文件系统:root和latestProduct对应于目录,user, url和name对应于文件。url和name在目录latestProduct中。但这只是一个比喻,其实并没有真正的文件和目录。

当FreeMarker将上面的数据模型与示例模版合成时,web页面的访问者就会得到如下输出:

<html>

<head>

  <title>Welcome!</title>

</head>

<body>

  <h1>Welcome Big Joe!</h1>

  <p>Our latest product:

  <a href="products/greenmouse.html">green mouse</a>!

</body>

</html> 

 

 

 

数据模型  The data model 

正如你已经看到的,数据模型是基于树形结构的。这棵树可以任意复杂,并且不限深度:

(root)

  |

  +- animals

  |   |

  |   +- mouse

  |   |   |  

  |   |   +- size = "small"

  |   |   |  

  |   |   +- price = 50

  |   |

  |   +- elephant

  |   |   |  

  |   |   +- size = "large"

  |   |   |  

  |   |   +- price = 5000

  |   |

  |   +- python

  |       |  

  |       +- size = "medium"

  |       |  

  |       +- price = 4999

  |

  +- test = "It is a test"

  |

  +- whatnot

      |

      +- because = "don't know" 

其中作为目录的变量(the root, animals,
15070
mouse, elephant, python, whatnot)叫做散列hashes。哈西使用查找名来存放其它子变量。

存储单个值的变量叫做标量scalars

当你访问一个子变量时,必须使用从根root开始的、以句点.分割的路径。比如要访问老鼠mouse的价格price,从根root开始到animals,然后到mouse,再到price。所以应该这样写:animals.mouse.price。当你用特殊代码${...}包围这样的表达式,就是告诉FreeMarker输出这个节点的相应文本。比如:${ animals.mouse.price }???

还有一个重要的变量:序列sequences。序列与散列类似,都可以包含子变量,但是没有相应的查找名,而是使用序列存储子变量,可以通过数字下标访问子变量。比如,在下面的数据模型中,animals和whatnot.fruits都是序列:

(root)

  |

  +- animals

  |   |

  |   +- (1st)

  |   |   |

  |   |   +- name = "mouse"

  |   |   |

  |   |   +- size = "small"

  |   |   |

  |   |   +- price = 50

  |   |

  |   +- (2nd)

  |   |   |

  |   |   +- name = "elephant"

  |   |   |

  |   |   +- size = "large"

  |   |   |

  |   |   +- price = 5000

  |   |

  |   +- (3rd)

  |       |

  |       +- name = "python"

  |       |

  |       +- size = "medium"

  |       |

  |       +- price = 4999

  |

  +- whatnot

      |

      +- fruits

          |

          +- (1st) = "orange"

          |

          +- (2nd) = "banana" 

要访问序列的子变量,需要使用类似于数组的下标机制,将下标放到中括号中。下标从0开始,第二个变量的下标是1,以此类推。所以要获得第一个动物的名字,使用animals[0].name。要获得whatnot.fruits中的第二个条目(这里是字符串"banana"),使用whatnot.fruits[1]。

标量可以存储不同类型的值。最常用的类型有:

字符串:文本、字符序列。要在FreeMarker中使用字符串,必须使用引号,如"mouse" 或 'mouse'。

数字:就是数值。字符串"50"与数值50是完全不同的。前者是两个字符(尽管读音与数字相同),而后者是一个可以用于数学计算的数字值。所以,不要用引号包围数字!这会使FreeMarker将该量作为字符串处理。合法的数字有:0, 4999, -273, 3.14。

总结:

数据模型可以视作是层次结构的 --  就像是树。

标量scalar存储单值。可以存储字符串或数字(还有别的东西,稍后介绍)。

散列hash是用于存储其它变量的容器,并具有查找名。

序列sequence是一种按顺序存储其它变量的容器。可以通过数字下标进行访问。

 

模版  The template 

最简单/常见的模版是HTML文件。当客户端访问页面时,FreeMarker就会将该HTML原封不动的发送到客户端。但如果你想获得动态效果,就会在HTML中特定位置放置一些FreeMarker可以识别的东西:

·         占位符${...}:FreeMarker会在输出中使用括号中内容相对应的实际值来替换它。
·         FTL标签(FreeMarker Template Language tags:FTL标签与HTML标签相似,但它们是FreeMarker的内容,并不会打印到输出中。FTL标签名以井号”#”开头,以便于HTML标签区分开来。(其实还可以用” @”代替”#”,后续章节会解释)
·         注释Comments:与HTML注释类似,只是由<#-- 和 -->来界定(而不是<!—和 -->)。这两个界定符之间的任何内容都会被FreeMarker忽略,并且不会打印到输出中。
任何既不是FTL标签也不是占位符或注释的内容都被当作普通文本来处理,并且不会被FreeMarker解析,而直接打印到输出中。

FTL标签也称为“指令”directives。就像是HTML标签也被叫做HTML元素,比如<table>和</table>也叫做table元素。如果你感觉二者没有区别,可以把“FTL标签”和“指令”作为同义词。

指令的例子  Examples of directives 

尽管FreeMarker有很多的指令,但这个小例子只使用最常用的指令中的三个。

if指令  The if directive 

使用if指令可以根据条件跳过模版的一个部分。比如,假设在第一个例子very first example中,你想将你的老板于其它用户区分开来,假设你老板的名字叫Big Joe:

<html>

<head>

  <title>Welcome!</title>

</head>

<body>

  <h1>

    Welcome ${user}<#if user = "Big Joe">, our beloved leader</#if>!

  </h1>

  <p>Our latest product:

  <a href="${latestProduct.url}">${latestProduct.name}</a>!

</body>

</html> 

在模版中,你告诉FreeMarker字符串“, our beloved leader”只有在变量user的是值是字符串"Big Joe"时才显示。通常,如果条件condition的值为false时,在<#if condition>与</#if>标签中的内容。

注意:这里使用了两种不同语法的元素。等号=的左边,使用了一个变量,右边使用了字符串。也可以这样写(使用基于散列样例的数据模型):

<#if animals.python.price < animals.elephant.price>

  Pythons are cheaper than elephants today.

</#if> 

使用<#else>标签可以制定当条件为假时要做什么:

<#if animals.python.price < animals.elephant.price>

  Pythons are cheaper than elephants today.

<#else>

  Pythons are not cheaper than elephants today.

</#if> 

如果python的价格比大象elephant的价格低,会输出”Pythons are cheaper than elephants today.”,否则输出“Pythons are not cheaper than elephants today.”。

list指令  The list directive 

当你想列举一些内容的时候,应该使用list指令。如果将这个模版与前面的序列样例数据模型合并:

<p>We have these animals:

<table border=1>

  <tr><th>Name<th>Price

  <#list animals as being>

  <tr><td>${being.name}<td>${being.price} Euros

  </#list>

</table> 

会输出:

<p>We have these animals:

<table border=1>

  <tr><th>Name<th>Price

  <tr><td>mouse<td>50 Euros


  <tr><td>elephant<td>5000 Euros


  <tr><td>python<td>4999 Euros

</table> 

list指令的通用格式是:

<#list SequenceVar as variable>repeatThis</#list>

<#list 序列变量 as 变量>重复内容</#list>

repeatThis重复内容 部分就是当在给定的序列变量SequenceVar中的每个条目被遍历(从第一个开始)时所要重复的内容。每重复一次,变量variable就会持有当前条目的值。这个变量只存在于<#list ...>与</#list>内,并且不会重写/覆盖任何位于数据模型中的同名变量。

再来一个例子,将前面数据模型中的水果列出来:

<p>And BTW we have these fruits:

<ul>

<#list whatnot.fruits as fruit>

<li>${fruit}

</#list>

<ul> 

注意:你应该已经熟悉whatnot.fruits了,它是对数据模型中的变量的引用。

include指令  The include directive 

使用include指令可以将外部文件导入模版(译注:与html、jsp中的include类似)。

比如,如果你要在多个页面显示相同的版权信息。可以创建一个只包含版权声明的文件,然后将其插入你需要显示版权声明的任何地方。假设将版权声明放到copyright_footer.html中:

<hr>

<i>

Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>,

<br>

All Rights Reserved.

</i> 

在任何需要的地方使用include指令插入即可:

<html>

<head>

  <title>Test page</title>

</head>

<body>

  <h1>Test page</h1>

  <p>Blah blah...

<#include "/copyright_footer.html">

</body>

</html> 

会输出:

<html>

<head>

  <title>Test page</title>

</head>

<body>

  <h1>Test page</h1>

  <p>Blah blah...

<hr>


<i>


Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>,


<br>


All Rights Reserved.


</i>

</body>

</html> 

如果修改copyright_footer.html,就会在所有的页面中看到新的版权声明。

结合使用多个指令  Using directives together 

你可以在一个页面中使用任意数量的指令,也可以自由的嵌套指令。比如下面的例子会列出所有的动物并将大型动物的名称以粗体显示:

<p>We have these animals:

<table border=1>

  <tr><th>Name<th>Price

  <#list animals as being>

  <tr>

    <td>

      <#if being.size = "large"><b></#if>

      ${being.name}

      <#if being.size = "large"></b></#if>

    <td>${being.price} Euros

  </#list>

</table> 

注意:由于FreeMarker不对FTL标签外部的文本进行解析,所以占位符和注释不会将上面的<b>和</b>视为嵌套错误的标签。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息