如何在enlive中使用代码片段?

9
我是一名Ruby on Rails 开发者,在接触Clojure方面还比较新手。我试图做一些在ERB中非常简单的事情,但是在enlive中却让我很难理解。
假设我有一个简单的网站布局文件layout.html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>

我有一些代码片段,例如header.html和footer.html以及这个简单的路由。

(deftemplate layout "layout.html" [])

(defroutes home-routes
  (GET "/" [] layout))

如何让每次请求“/”时,都可以将布局转换并插入头部和底部片段?

2个回答

11

defsnippet只匹配html的特定部分(这就是为什么它以选择器作为参数),并进行转换。 deftemplate则接收整个html,然后进行转换。此外,defsnippet返回Clojure数据结构,而deftemplates返回字符串向量,因此通常在deftemplate内使用defsnippet。

为了让你了解片段(或选择器)返回的数据结构是什么样子:

(enlive/html-snippet "<div id='foo'><p>Hello there</p></div>")
;=({:tag :div, :attrs {:id "foo"}, :content ({:tag :p, :attrs nil, :content ("Hello there")})})

在您的情况下,您想要类似以下内容:

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>"

1
谢谢!针对未来读者的更正。这一行(enlive/defsnippet header "path/to/header.html" [:#my-header-root] identity)在选择器后应该有一个向量。所以它应该是:(enlive/defsnippet header "path/to/header.html" [:#my-header-root] [] identity)。页脚的defsnippet也是如此。 - Chris Bui
1
啊,错过了那个。我已经相应地更新了示例。 - ebaxt

0

enlive教程中有很好的答案和示例。

警告。所有源文件链接似乎都已损坏。您需要在所有链接后插入enlive-tutorial/blob/master/,或直接从教程项目中打开它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接