模板引擎快速开始
ace-template 是 ACE Framework 的模板渲染组件,特点:
- 零反射、纯仓颉:
engine子包只依赖std,词法/语法/渲染全部编译期无关的显式代码,可离线单测;数据用显式TemplateValue建模,不做运行时内省 - 一个 import 完成装配:
import ace_template.*即触发TemplateComponent自注册,配置驱动,@Inject TemplateEngine即可用 - 逻辑轻量(Mustache 风格)+ 完整特性:插值/section/反转/注释/局部模板/点分路径,外加过滤器链、循环元数据、模板继承、自定义分隔符、standalone 空白处理、上下文感知转义与 JSON 桥接
- 默认防 XSS:
{{ x }}插值默认 HTML 转义(含反引号)
引入
cjpm.toml 添加依赖:
toml
[dependencies]
ace_web = { path = "../../ace-web" }
ace_framework = { path = "../../ace-framework/ace-framework" }
ace_framework_macros = { path = "../../ace-framework/ace-framework-macros" }
ace_template = { path = "../../ace-template" }业务代码 import:
cangjie
import ace_framework.*
import ace_framework_macros.*
import ace_template.* // 触发 TemplateComponent 自注册配置
配置命名空间 [template](application.toml),所有键都有合理默认值:
toml
[template]
enabled = true # 条件装配开关
dir = "templates" # 模板根目录(按进程 cwd 相对解析)
suffix = ".mustache" # 模板文件后缀
cache = true # 缓存已解析 AST(解析一次、渲染多次)| 键 | 默认 | 说明 |
|---|---|---|
enabled | true | 关闭后组件整体不装配 |
dir | templates | 文件加载器的模板根目录;engine.render("index", ...) 读 dir/index+suffix |
suffix | .mustache | 模板文件扩展名(可设 .html) |
cache | true | 是否缓存解析结果 |
渲染第一个页面
模板文件 templates/hello.mustache:
html
<h1>你好,{{ name }}!</h1>
{{#items}}<li>{{@number}}. {{ . }}</li>{{/items}}控制器 @Inject TemplateEngine,用 renderView 按名渲染并回写 text/html:
cangjie
@Controller[""]
public class HomeController {
@Inject
var engine: TemplateEngine
@Get["/"]
public func home(ctx: Context): String {
let model = TemplateModel()
.set("name", "ACE")
.set("items", tstrList(["路由", "宏", "ORM"]))
// renderView 内部 ctx.html(engine.render(...)) 并返回 "" 哨兵
return renderView(ctx, engine, "hello", model)
}
}控制器约定:路由方法返回类型声明为
String。renderView(ctx, engine, name, model)会经ctx.html(...)设好响应体与Content-Type: text/html,并返回""空串哨兵——框架约定处理器返回""时不覆盖已写好的响应体。也可直接ctx.html(engine.render(...))后return ""。
三种渲染入口
cangjie
// 1) 按名渲染:走文件加载器(dir/name+suffix),AST 缓存
engine.render("hello", model)
// 2) 内联渲染:直接渲染源串,不读文件
engine.renderString("<p>Hi {{ name }}</p>", model)
// 3) 显式注册命名模板/局部模板(优先于文件加载器)
engine.register("row", "<td>{{ n }}</td>")下一步
- 模板语法 —— 插值、section、循环元数据、继承、自定义分隔符全参考
- 过滤器与助手 —— 内置过滤器、
registerFilter自定义助手、上下文转义与安全 - 数据模型与 JSON 桥接 ——
TemplateModel构造与jsonToTemplateValue