Om如何渲染列表对象?

3

我很难理解Om如何使用apply来渲染列表项,就像下面从Om教程页面中提取的示例一样。

(om/root
  (fn [data owner]
    (om/component 
      (apply dom/ul nil
        (map (fn [text] (dom/li nil text)) (:list data)))))
  app-state
  {:target (. js/document (getElementById "app0"))})

我的理解是,apply函数接受一个函数和一个列表,并将该函数应用于列表。但在这个例子中,这种理解将转化为将dom/ul应用于nil

我不明白的是:

  • 为什么要将dom/ul应用于列表?我不想创建ul元素,我想创建li元素。
  • 在这个例子中,apply如何处理所有发送的参数?
2个回答

2

dom/ul是一个函数,它会生成一个React组件来渲染相应的DOM元素。dom/ul的第一个参数指定了您希望DOM元素具有的属性。例如,如果您想要dom/ul的class属性设置为"main",则可以执行以下操作:

  (apply dom/ul #js {:className "main"}
    (map (fn [text] (dom/li nil text)) (:list data)))

dom/ul的第一个参数设置为nil,只是不设置DOM属性。
Clojure的apply通过将所有参数(在dom/ul参数之后)前置到最终列表中(由map生成)的参数,并将结果作为参数传递给dom/ul来调用dom/ul
例如,假设data具有以下值:
["Apple" "Bird"] 

那么在您的示例中,dom/ul 最终会被调用为:

(dom/ul nil
    (dom/li nil "Apple")
    (dom/li nil "Bird"))

这将导致以下HTML被呈现:
<ul>
  <li>Apple</li>
  <li>Bird</li>
</ul>

2
当我刚开始学习Om时,我花了一些时间才理解这个。需要记住的关键是每个om.dom函数的第一个参数都是一个JS属性映射,然后是任意数量的om.dom参数。可能像我一样预期的是 om.dom 函数将使用属性和dom元素向量。一旦明白了这一点,Om的设计就更有意义了。
Clojure的apply函数“展开”集合并将集合的元素作为要应用的函数的参数传递。所以我们计算的中间步骤为:
(apply dom/ul nil
    (map (fn [text] (dom/li nil text)) (:list data)))

那么

(apply dom/ul nil
    '((dom/li nil "Hi") (dom/li nil "there")))

那么

(dom/ul nil
    (dom/li nil "Hi") (dom/li nil "there"))

没有使用apply,我们将无法向dom/ul传递正确的参数。你还会看到apply与om/build-all一起使用,它返回一个类似于map的集合。
再举一个例子来扩展这个概念,如果我们想在dom/p中放置两个dom/ul,则完整的形式如下:
(dom/p nil
    (dom/ul nil (dom/li nil "Hi") (dom/li nil "there"))
    (dom/ul nil (dom/li nil "Next") (dom/li nil "list")))

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