【问题标题】:Using Om, Generate Nested divs From a Nested Map使用 Om,从嵌套地图生成嵌套 div
【发布时间】:2015-03-06 04:52:22
【问题描述】:

假设我有以下地图:

(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 上映射递归函数。它会将地图分开,直到它看到一个叶子,然后冒泡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 元素的奖励积分..

【问题讨论】:

    标签: clojure clojurescript om


    【解决方案1】:

    在解决此类问题时,有时在 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"))
    

    【讨论】:

    • 这是迄今为止最好的答案。
    【解决方案2】:

    以下代码生成的 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" {}}))))
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        对于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 {}} 元素。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-06-06
          • 1970-01-01
          • 1970-01-01
          • 2021-09-15
          • 2015-06-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多