我想为Om组件创建一个单击处理函数。我发现的docs和Stack Overflow示例总是声明像这样的匿名函数
(defn main-view [_ owner]
(reify
om/IRender
(render [_]
(let [xs (items)]
(dom/div nil
(om/build sub-view {:title "View A"})
(om/build sub-view {:title "View B"})
(dom/button
#js {:onClick
(fn [e] (om/transact! xs #(assoc % 1 {:text "zebra"})))}
"Switch To Zebra!"))))))
我认为在组件内部声明jsx / template区域外的click函数比常规React中通常做的更简洁。在组件中有没有办法在Om中执行此操作?我尝试过这个,但它不起作用因为onClick未定义:
(defn my-component []
(reify
om/IRender
(render [this]
; Using Sablono syntax
(html [:h1 "Here is a heading" {:on-click 'onClick} ]))
onClick
(onClick [this]
; this part never gets executed when you click
(.log js/console "click"))))
如果可能的话,我想避免在组件外部定义单独的函数。
答案 0 :(得分:5)
你的问题是明智的,而且是关于处理数据的范围。
这是可能的,但在大多数情况下,这种方法的问题是你需要来自外部代码块的本地范围数据(在你的情况下,它是一个Om组件)。
我会在代码中解释。假设你要移出处理函数:
(anything
(let [a 1 b 2]
(on-event (fn my-handler [evt] (log (+ a b (.someAttr evt)))))))
你最终会得到更长的时间:
(defn local-data->handler [a b]
(fn [evt] (log (+ a b (.someAttr evt)))))
(anything
(let [a 1 b 2]
(on-event (local-data->handler a b))))
如果您只是想在组件定义中移动:
(anything
(let [a 1
b 2
my-handler (fn [evt] (log (+ a b (.someAttr evt))))]
(on-event my-handler)))
请注意:为了保持事件处理程序的正常运行,请确保您的非匿名函数(使用defn或let创建)与匿名表单相同,尤其是参数列表。
onClick未定义,因为您使用它就好像它是一个Om协议。有关正确使用的信息,请参阅Om生命周期协议。
答案 1 :(得分:2)
根据您的要求,您应该将功能定义移出组件。
然后,您应该能够将函数的名称传递给事件监听器:
(defn foo [] (println "foo"))
(defn my-component [text owner]
(reify
om/IRender
(render [_]
(dom/button
#js { :onClick foo }
"Click Here"))))