不,这不会像你期望的那样工作。要了解差异,请考虑以下两个组件:
(defn test-component-if []
(let [a (atom 1)
_ (.log js/console "let in -if")]
(if (odd? @a)
[:div
[:p "odd"]
[:button {:on-click #(swap! a inc)}
"inc"]]
[:div
[:p "even"]
[:button {:on-click #(swap! a inc)}
"inc"]])))
(defn test-component-fn []
(let [a (atom 1)
_ (.log js/console "let in -fn")]
;; I dub thee test-inner
(fn []
(if (odd? @a)
[:div
[:p "odd"]
[:button {:on-click #(swap! a inc)}
"inc"]]
[:div
[:p "even"]
[:button {:on-click #(swap! a inc)}
"inc"]]))))
test-component-fn
按预期工作,而test-component-if
没有。这是为什么?好吧,当一个试剂组件可以返回两件事之一时(我忽略了“类型 3”组件,因为它与反应知识挂钩)。它可以返回
- 一个向量
- 另一个功能
如果它返回一个向量,函数本身就成为渲染函数,在我们的例子test-component-if
中。当它返回一个函数时,返回的函数,而不是原始函数,是渲染函数。在这种情况下,我所配音的test-inner
当 Reagent 调用渲染函数时,它会跟踪函数访问的原子,并且每当该原子发生变化时,它都会调用渲染函数。那么当我们使用时会发生什么test-component-if
?
- 试剂调用
test-component-if
- 我们的 let 子句将一个新原子绑定
a
到 1。
- 返回一个向量
- 我们点击按钮
- 原子
a
递增
- 试剂看到变化
a
并调用test-component-if
- 我们的 let 子句将一个新原子绑定
a
到 1。(与我们之前的不同原子a
)
- 哎呀!
总是 1。您可以通过查看控制台来验证这a
一点,并看到每次单击按钮时都会打印消息。
现在怎么样test-component-fn
?
- 试剂调用
test-component-fn
- 我们的 let 子句将一个新原子绑定
a
到 1。
test-component-fn
返回test-inner
关闭a
- 试剂调用
test-inner
- 我们点击按钮
a
递增
- 试剂看到变化
a
并调用test-inner
- 根据需要重复多次。
您可以验证 let only 在控制台上再次执行。根据需要多次单击按钮,消息只会在第一次呈现时打印。
就if
没有else
子句而言,这确实会返回 nil。在这种情况下使用when而不是使用是惯例if
,这清楚地表明缺少 anelse
是有意的。它还具有包含隐式do的优点。至于 Reagent 遇到这种情况会怎么做nil
,大多数情况下它会默默地移除它,什么也不显示。