有什么方法可以在不使用匿名函数的情况下在 Om 中创建 onClick 处理程序吗?
Is there any way to make an onClick handler in Om without using anonymous function?
我想为 Om 组件创建一个点击处理函数。我发现的文档和 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 区域之外、在组件内声明点击函数会更清晰,这是在常规 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"))))
如果可能的话,我想避免在组件外部定义一个单独的函数。
根据您的要求,您应该将函数定义移出组件。
然后您应该能够将函数的名称传递给事件侦听器:
(defn foo [] (println "foo"))
(defn my-component [text owner]
(reify
om/IRender
(render [_]
(dom/button
#js { :onClick foo }
"Click Here"))))
你的问题很合理,是关于处理数据范围的问题。
这是可能的,但在大多数情况下,这种方法存在问题,您将需要来自外部代码块的本地范围数据(在您的情况下,它是一个 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 生命周期协议以了解正确用法。
我想为 Om 组件创建一个点击处理函数。我发现的文档和 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 区域之外、在组件内声明点击函数会更清晰,这是在常规 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"))))
如果可能的话,我想避免在组件外部定义一个单独的函数。
根据您的要求,您应该将函数定义移出组件。
然后您应该能够将函数的名称传递给事件侦听器:
(defn foo [] (println "foo"))
(defn my-component [text owner]
(reify
om/IRender
(render [_]
(dom/button
#js { :onClick foo }
"Click Here"))))
你的问题很合理,是关于处理数据范围的问题。
这是可能的,但在大多数情况下,这种方法存在问题,您将需要来自外部代码块的本地范围数据(在您的情况下,它是一个 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 生命周期协议以了解正确用法。