使用Om,从嵌套地图生成嵌套div

时间:2015-03-06 04:52:22

标签: clojure clojurescript om

说我有以下地图:

(def m {"a" {"d" {}
             "e" {}}
        "b" {"f" {}
             "g" {"h" {}
                  "i" {}}}
        "c" {}})

我需要像这样渲染它:

(om.dom/div #js {} "a" 
  (om.dom/div #js {} "d")
  (om.dom/div #js {} "e"))

(om.dom/div #js {} "b" 
  (om.dom/div #js {} "f")
  (om.dom/div #js {} "g"
    (om.dom/div #js {} "h")
    (om.dom/div #js {} "i")))

(om.dom/div #js {} "c")

我该怎么做呢?我和clojure.walk混淆了,但是不能先让叶子上的om.dom/div,然后是直接父母等等。

我认为解决方案可能涉及在给定子映射的vals上映射递归函数。它会将地图分开,直到它看到 leaf ,然后将om.dom/div调用重新映射回地图。

到目前为止,我有这个功能:

(defn build-tree [data]
  (apply dom/div #js {}
         (->> (clojure.walk/postwalk
                #(cond (map? %) (vec %)
                       (vector? %) %
                       (string? %) %) data)
              (clojure.walk/postwalk
                #(if (and (vector? %) (string? (first %)))
                   (apply dom/div #js {} %) %)))))

结果是:

在检查员中使用此功能:


用于生成嵌套dom/uldom/li元素的加分点..

4 个答案:

答案 0 :(得分:3)

在解决此类问题时,有时生成类似于REPL所需调用树的树结构很有帮助。一旦结果看起来没问题,将其转换为实际的调用树通常很简单。

例如,这是为您的示例生成om.dom/div调用树的函数;要在ClojureScript中使用,请按照评论中的说明进行调整:

(defn div [m]
  (for [[k v] m]
    ;; replace with (apply om.dom/div #js {} k (div v)) in CLJS
    (list* 'om.dom/div {} k (div v))))

示例电话:

(div {"a" {"d" {}
           "e" {}}
      "b" {"f" {}
           "g" {"h" {}
                "i" {}}}
      "c" {}})

以上输出:

;; in CLJS, you'll want to use this as the ... in
;; (apply create-container-component initial-args ...)
((om.dom/div {} "a"
   (om.dom/div {} "d")
   (om.dom/div {} "e"))
 (om.dom/div {} "b"
   (om.dom/div {} "f")
   (om.dom/div {} "g"
     (om.dom/div {} "h")
     (om.dom/div {} "i")))
 (om.dom/div {} "c"))

答案 1 :(得分:0)

以下代码生成的DOM结构看起来非常接近您要查找的内容,除了子节点(即使没有任何节点)包含在div中,这个应该很容易修复:

(defn tree-component
  [tree]
  (apply dom/div nil
         (keep (fn [[k v]]
                 (when k
                   (dom/div nil k
                            (tree-component v))))
               tree)))

(defn app-view
  [data owner]
  (reify
    om/IRender
    (render [_]
      (tree-component
        {"a" {"d" {}
              "e" {}}
         "b" {"f" {}
              "g" {"h" {}
                   "i" {}}}
         "c" {}}))))

答案 2 :(得分:0)

clojure.walk很棒,但有时候会变得更难。我有这个:

 (defn recursive-component [el]
   (cond
    (empty? el) nil
    (vector? el) (apply dom/div nil 
                      (first el)
                      (recursive-component (second el)))
    (map? el) (map recursive-component el)))


 (defn main-component [data owner]
   (om/component
    (apply dom/div nil "Main"
           (recursive-component m))))

答案 3 :(得分:0)

ulli

(defn recursive-component [el]
  (cond
   (and (vector? el) (empty? (second el)))
   (dom/li nil (first el))

   (vector? el) (apply dom/ul nil 
                     (first el)
                     (recursive-component (second el)))

   (map? el) (map recursive-component el)))

但它显示为li {:c {}}元素。