Составление шаблонов с помощью Hiccup и Compojure
Я относительно новичок в веб-разработке Clojure и Compojure. Первая проблема, которую я заметил в игрушечном примере, который я строю, это проблема HTML-шаблонирования. Я хотел бы иметь поддержку чего-то вроде партиалов в Rails или шаблонной структуры, которую использует Django.
В настоящее время у меня есть:
(defn index-page []
(html5
[:head
[:title "Home | Compojure Docs"]
(include-css "/css/bootstrap.min.css")
(include-css "/css/bootstrap-responsive.min.css")]
[:body
[:div {:class "container-fluid"}
[:div {:class "row-fluid"}
[:div {:class "span2 menu"}]
[:div {:class "span10 content"}
[:h1 "Compojure Docs"]
[:ul
[:li
[:a {:href "/getting-started"} "Getting Started"]]
[:li
[:a {:href "/routes-in-detail"} "Routes in Detail"]]
[:li
[:a {:href "/destructuring-syntax"} "Destructuring Syntax"]]
[:li
[:a {:href "/nesting-routes"} "Nesting Routes"]]
[:li
[:a {:href "/api-documentation"} "API Documentation"]]
[:li
[:a {:href "/paas-platforms"} "PaaS Platforms"]]
[:li
[:a {:href "/example-project"} "Example Project"]]
[:li
[:a {:href "/example-project-on-cloudbees"} "Example Project on CloudBees"]]
[:li
[:a {:href "/interactive-development-with-ring"} "Interactive Development with Ring"]]
[:li
[:a {:href "/emacs-indentation"} "Emacs Indentation"]]
[:li
[:a {:href "/sessions"} "Sessions"]]
[:li
[:a {:href "/common-problems"} "Common Problems"]]]
(include-js "/js/jquery-1.9.1.min.js")
(include-js "/js/bootstrap.min.js")]]]]))
(defn routes-in-detail []
(html5
[:head
[:title "Routes in Detail | Compojure Docs"]
(include-css "/css/style.css")]
[:body
[:h1 "Routes in Detail"]]))
Есть ли хороший способ для меня не повторять код? Мне бы хотелось, чтобы содержимое тега HEAD находилось в его собственном файле шаблона или функции, а затем я мог включать его по мере необходимости. Например, я хотел бы включить его в функцию "маршруты в деталях". Я посмотрел на Enlive, но я не уверен, как использовать это с Hiccup. Любые мысли о лучших практиках здесь будут оценены.
2 ответа
Вы можете вытащить части разметки в отдельные переменные:
(def head
[:head
[:title "Home | Compojure Docs"]
(include-css "/css/bootstrap.min.css")
... ])
(defn routes-in-detail []
(html5
head
[:body
... ]))
Если вам нужен ваш фрагмент / частичный для получения параметров, вы можете вместо этого превратить его в функцию, например:
(defn head [title]
[:head
[:title title]
(include-css "/css/bootstrap.min.css")
... ])
(defn routes-in-detail []
(html5
(head "Routes in detail")
... ))
Иногда вы хотите, чтобы ваш "фрагмент" состоял из нескольких элементов верхнего уровня, а не из одного. В этом случае вы можете заключить их в список - икота развернет его в строке:
(defn head-contents [title]
(list [:title title]
(include-css "/css/bootstrap.min.css")
... )))
(defn routes-in-detail []
(html5
[:head (head-contents "Routes in detail")]
[:body ... ]))
Как только вы поймете, что разметка икота сделана из простых структур данных clojure, вы обнаружите, что манипулирование / создание ее с помощью функций является простым и гибким.
Есть новая библиотека шаблонов под названием clabango
которая смоделирована по шаблонной библиотеке Django, это может быть то, что вы ищете: https://github.com/danlarkin/clabango