defsnippet只匹配html的特定部分(这就是为什么它以选择器作为参数),并进行转换。 deftemplate则接收整个html,然后进行转换。此外,defsnippet返回Clojure数据结构,而deftemplates返回字符串向量,因此通常在deftemplate内使用defsnippet。
为了让你了解片段(或选择器)返回的数据结构是什么样子:
(enlive/html-snippet "<div id='foo'><p>Hello there</p></div>")
在您的情况下,您想要类似以下内容:
header.html:
<div id="my-header-root">
...
</div>
Clojure 代码:
(enlive/defsnippet header "path/to/header.html" [:#my-header-root] []
identity)
(enlive/defsnippet footer "path/to/footer.html" [enlive/root] []
identity)
(enlive/deftemplate layout "layout.html" [header footer]
[:head] (enlive/content header)
[:body] (enlive/append footer))
(defroutes home-routes
(GET "/" [] (layout (header) (footer))
在这些代码片段中使用的身份函数返回其参数,此处参数为通过选择器 :#my-header-root 选定的数据结构(我们不进行任何转换)。如果您想包含 i.e head.html 中的所有内容,则可以使用 enlive 提供的根选择器步骤。
您可以使用类似以下方式查看 defsnippet 生成的 HTML:
(print (apply str (enlive/emit* (my-snippet))))
我还推荐使用教程:https://github.com/swannodette/enlive-tutorial/以及Brian Marick的另一个教程,以了解defsnippet和deftemplate宏的更多详情。
最后一个提示:您可以使用enlive附带的sniptest宏来尝试选择器和转换。
(enlive/sniptest "<p>Replace me</p>"
[:p] (enlive/content "Hello world!"))
;= "<p>Hello world!</p>"