ocTemplate 是一个为“面向二次发开项目”而设计的 Node.js 模板引擎。
ocTemplate 允许开发者使用 jQuery 处理模板结构,除此以外 ocTemplate 和其他的模板引擎没有太大的区别。 例如你正在开发一个blog程序而且采用了 ocTemplate 做为模板引擎,当有人基于你的blog程序进行二次开发时(他们使用你的blog程序,但是想改些地方), 可以不必修改你的模板源代码,而是在ocTemplate渲染一个模板前加载这个模板,用 jQuery 修改模板上的内容,就像在浏览器里操作网页元素一样。 这些操作都在后端 Nodejs 里实现。
你可以在模板上使用这些jQuery函数来控制模板的内容和结构:$.fn.append()/prepend()/after()/before()/attr()/addClass()/removeClass() ... ...
在二次开发时避免修改原来程序的源代码,有两个好处:
-
原来程序在发布新版本时,不会出现源代码冲突。
-
“补丁”代码可以作为独立的项目分发。
ocTemplate 依赖jsdom,并且对 jsdom 做了修改,解除了 jsdom 对 contextify C++ 的依赖,使 ocTemplate 能够在纯JavaScript环境中工作。
ocTemplate 没有像 jade 那样简化 html 语法,jade的模板语法简洁、干静,没有多余的字符,非常适合“敏捷”开发,但是无法和 jQuery 兼容。所以 ocTemplate 仍然保持完整的 html 语法。
快速开始
npm install octemplate
hello.js :
var tplCache = ; tplCache ;
templates/hello.html :
hello, world. Value of the variable foo is: {@foo}
安装开发版本(使用最新但不稳定的代码)
mkdir node_modules
cd node_modules
git clone git@github.com:OpenComb/ocTemplate.git octemplate
cd octemplate
git checkout 0.1.3
表达式
模板表达式的基本形式是:{@ expression }
,它可以用于文本和标签属性中。
Value of the variable foo is: {@foo}
在标签中使用模板表达式:
渲染后的结果是:
在标签的属性值中使用模板表达式:
作为标签的属性值:
所有以@
开头的属性值,将被视做一个表达式,计算后的结果以字符串的形式输出。
注意:有些模板标签的属性必须是表达式才有意义,漏掉
@
模板引擎不会报告错误,但逻辑并不正确,这是一个常见的新手错误。例如:
Variable foo is avalid.
这是错误的,condition 会收到一个字符串:"foo"
而不是变量 foo
,因此判断总是为 true 。
<!-- 不能漏掉那个 @ -->Variable foo is avalid.
多行表达式
ocTemplate 仅支持单行表达式,如果提供多行表达式,只会执行第一行并返回其结果。
result of expression: {@ var i=123; return i } .
渲染结果:
result of expression: undefined .
这不是预期的效果。这种情况下,可以使用匿名函数来包装多行表达式:
result of expression: {@ (function(){ var i=123; return i ;})() } .
渲染结果:
result of expression: 123 .
用 (function(){ ... })()
模式将多行表达式包装起来即可。
$model
预置变量$model
是模板中所有变量的名称空间。
tpl.render()
的参数 model 中的内容都在 $model
中;所有$model
对象的属性,都可以在模板表达式中作为独立的变量使用。
例如:
{@foo}
或者:
{@$model.foo}
对于变量foo
,{@foo}
和 {@$model.foo}
这两种写法:
-
如果
foo
变量存在,两者具有效果相同; -
如果
foo
变量不存在,则{@foo}
抛出异常(会打断后文的模板内容渲染),{@$model.foo}
则输出undefined
。
简单的说,和JavaScript的标准行为一致。
因此如果不能保证 foo 变量一定存在,使用 {@$model.foo}
代替 {@foo}
{@$model.foo}
的效果类似于:
```html
<div>
{@ typeof foo!='undefined'? foo: undefined}
</div>
```
标签
<if>
属性:
- [必须]
condition
: 条件表达式
example:
{@foo}
注意:不要漏掉 condition 属性里的
@
,否则会被当作一个字符串,那多半不是你想要的效果。
<foreach>
属性:
-
[必须]
for
: 循环目标对象表达式,表达式返回的结果可以是 Object 或 Array 。 -
[可选]
var
: 迭代变量名称,创建对应变量保存每一轮迭代出来的值。var
需要的是一个字符串作为变量名称,如果提供表达式,则表达式的结果会被转换成字符串传递给var
(这可能不是你想要的)。 -
[可选]
key
: 迭代键或下标变量名称。提供给
for
属性的如果是一个 Object,则key
对应名称的变量中存入的是Object的属性名;如果提供Array类型给for
,则为数组下标。
example:
attribute {@key} of variable foo is: {@item}
注意:只有for属性是一个表达式(
@
开头),key
和var
只是简单是字符型属性值,它们作为变量名称
<loop>
这是一个简化的 for 循环。
<loop> 仅支持针对整数的迭代
属性:
-
[必须]
end
: 循环结束数值(包含end
值)。 -
[可选]
start
: 循环开始数值。默认为:1。 -
[可选]
step
: 循环步长。默认为:1。 -
[可选]
var
: 迭代变量名称,创建对应变量保存每一轮迭代出来的值。
这些属性可以是普通属性值或表达式,无论什么类型都会被转换成整数。
example:
foo = 7
{@ value}
结果:
2
4
6
<elseif>
在所有流程控制标签中提供 else if 效果;支持: <if>, <loop>, <foreach> 等
属性:
- [必须]
condition
, 参看 <if> 同名属性
<else>
在所有流程控制标签中提供 else 效果;支持: <if>, <loop>, <foreach> 等
无属性
<continue>
在所有流程控制标签中提供 continue 效果;支持: <if>, <loop>, <foreach> 等
无属性
<break>
在所有流程控制标签中提供 break 效果;支持: <if>, <loop>, <foreach> 等
无属性
<include>
引用另一个模板。
属性:
-
[必须]
file
: 引用模板的文件路径,可以是表达式或普通文本属性。路径查找规则和 Nodejs 相同;如果提供给file的是一个相对路径,则相对当前模板的位置。
-
[可选]
model
: 传递给被引用模板的变量模型。如果希望将当前模板的所有变量都传给被应用模板,可以这样:
model="@$model"
。$model
是当前模板的名称空间。
$helper
某些较复杂的逻辑或表达式不适合出现在模板,我们将他们封装到了 $helper 对象中。
$helper
是一个对象,该对象提供了一组状态无关的方法,用来简化模板表达式的逻辑,预置了下列方法:
-
addslashes(text)
为
\
,"
,'
以及 0字节 添加转义斜线。 -
eq (lft,rgt)
如果 lft 和 rgt 相等(==),返回true,否则返回false。
-
gt (lft,rgt)
如果 lft 大于 rgt(>),返回true,否则返回false。
-
lt (lft,rgt)
如果 lft 小于 rgt(<),返回true,否则返回false。
-
ge (lft,rgt)
如果 lft 大于等于(>=) rgt,返回true,否则返回false。
-
le (lft,rgt)
如果 lft 小于等于(<=) rgt,返回true,否则返回false。
比较运算符中的
<
和>
与模板中的标签边界符号相冲突,所以必须使用 $helper 中的比较方法(compare methods)。
example:
variable foo is greater then variable bar . variable foo is not greater then variable bar .
后端 jQuery 操作
以上都是内容和其他模板引擎没有太大区别,接下来才是 ocTemplate 的重点。
ocTemplate 支持 jQuery, 每一个模板对象都可以被当作一个独立的 browser 环境,jQuery可以在模板对象(template)内运行,其行为和在浏览器里完全一致。
var tplCache = ; // 加载 templatetplCache ;
也可以在向模板中添加流程控制标签和表达式 (Cool!):
// ... // 在导航菜单中加入一个菜单项 // (使用 <if> 判断是否存在变量 username,并将 username 里的值输出到 alert 里 ) tpl
在 ocTemplate 的模板中执行事件相关的jQuery操作没有意义:有些事件可能不会触发,即使触发也不会发生在浏览器里,与用户交互无关。
一个错误的例子:
tpl ;
上面的用法实际上是混淆的前端和后端的区别,ocTempate 对jQuery 的支持,仅仅用于控制模板文件里的内容,不直接支持网页的前端行为。