2013-03-13 18 views
7

Sono relativamente nuovo allo sviluppo web Clojure e Compojure. Il primo numero che ho notato nell'esempio di giocattoli che sto creando è quello dei template HTML. Mi piacerebbe avere il supporto per qualcosa come partial in Rails, o il framework di template che Django usa.Composizione di modelli con Hiccup e Compojure

Attualmente ho:

(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"]])) 

C'è un buon modo per me di non ripetere il codice? Mi piacerebbe che le cose nel tag HEAD fossero nel proprio file modello o funzione, e quindi essere in grado di includerlo mentre procedo. Ad esempio, mi piacerebbe includerlo nella funzione 'routes-in-detail'. Ho guardato Enlive, ma non sono sicuro di come usarlo con Hiccup. Qualsiasi pensiero sulle migliori pratiche qui sarebbe apprezzato.

risposta

11

Si può tirare le parti del markup fuori in Vars distinte:

(def head 
    [:head 
    [:title "Home | Compojure Docs"] 
    (include-css "/css/bootstrap.min.css") 
    ... ]) 

(defn routes-in-detail [] 
    (html5 
    head 
    [:body 
     ... ])) 

Se è necessario il frammento/parziale a prendere i parametri, si può fare in una funzione, invece, ad esempio:

(defn head [title] 
    [:head 
    [:title title] 
    (include-css "/css/bootstrap.min.css") 
    ... ]) 

(defn routes-in-detail [] 
    (html5 
    (head "Routes in detail") 
    ...)) 

A volte vuoi che il tuo "frammento" sia composto da più elementi di primo livello piuttosto che da uno solo. In questo caso si possono avvolgere in una lista - singhiozzo sarà espanderlo in linea:

(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 ... ])) 

Una volta che ci si rende conto del fatto che la marcatura incidente di percorso è fatto di strutture dati clojure pianura, vi accorgerete che la manipolazione/costruirlo con le funzioni è facile e flessibile.

+0

Grazie per la risposta dettagliata. Questo e 'esattamente quello che stavo cercando. –

0

C'è una nuova libreria di template chiamato clabango che è modellato dopo la libreria di template Django, può essere quello che stai cercando dopo: https://github.com/danlarkin/clabango