使用Enlive作为模板引擎

在所有的clojure web开发例子里,对模板的介绍都很少。很多的简单例子都是以hiccup作为页面生成的手段。hiccup是个clojure的html DSL,例子里用这样的DSL生成页面确实很酷,可是他是real world吗,当然不是。

好在clojure世界里早就有了enlive,它不仅是一个通过css selector解析html的库,本身也可以作为模板引擎应用在web开发中。我不知道这种通过css selector的方式是否是enlive首创,不过他实在是非常新颖独特,而且平滑了页面设计和程序的集成。

例如这样一个模板 index.html:

<div id="cc">Sample Text</div>

在clojure程序中,使用enlive的deftemplate

(deftemplate index "index.html"
  [ctx]
  [:div#cc] (content (:data ctx)))

在控制器里,可以很MVC地渲染页面

(index {:data "rendered text"})

除了content用于渲染文本,还有html-content可以渲染含html标签的内容,以及set-attr用来修改页面元素的属性。

和传统的模板引擎相比,最大的不同是enlive里没有嵌入模板的直观的控制流,没有循环和条件判断,但是并非不可实现。

循环输出一组list

页面 list.html

<ul id="the-list">
<li class="list-item"></li>
</ul>

定义一个enlive的snippet

(defsnippet item-model "page.html" [:.list-item]
  [ctx]
  [:.list-item] (content (:data ctx)))

在页面模板里

(deftemplate list-page "list.html"
  [ctx]
  [:ul#the-list] (content (map item-model (:some-list ctx))))

这样在页面里列表项会被循环输出,而在页面设计时这里可以放任意个li,并且直接交给后台作为模板。

条件判断

页面,设计时显示所有的内容 msg.html

<span id="msg">只在一定条件下显示</span>

在模板中通过clojure的if进行判断

(deftemplate msg "msg.html"
  [ctx]
  [:span#msg] (if (:show ctx) identity (html-content "")))

解决了这两个问题,基本上用enlive作为模板引擎就没有障碍了。不过enlive也有一点小问题,其一可能是性能的问题,方便的selector显然要比传统的模板语言消耗更多的CPU。另外,在开发过程里,页面文件在服务器启动后不能热加载,修改页面必须重启ring才能看到。也许有时间的话,可以给它加一个reload选项。

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>