有没有办法在不使用匿名函数的情况下在Om中创建onClick处理程序?

lk1*_*145 3 clojurescript om

我想为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!"))))))
Run Code Online (Sandbox Code Playgroud)

我认为在组件内部声明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"))))
Run Code Online (Sandbox Code Playgroud)

如果可能的话,我想避免在组件外部定义单独的函数.

myg*_*tar 5

你的问题是明智的,它是关于处理数据的范围.

这是可能的,但在大多数情况下,这种方法的问题是你需要来自外部代码块的本地范围数据(在你的情况下,它是一个Om组件).

我会在代码中解释.假设你要移出处理函数:

(anything
 (let [a 1 b 2]
   (on-event (fn my-handler [evt] (log (+ a b (.someAttr evt)))))))
Run Code Online (Sandbox Code Playgroud)

你最终会得到这个更长的时间:

(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))))
Run Code Online (Sandbox Code Playgroud)

如果您只想在组件定义内移动:

(anything
 (let [a 1
       b 2
       my-handler (fn [evt] (log (+ a b (.someAttr evt))))]
   (on-event my-handler)))
Run Code Online (Sandbox Code Playgroud)

请注意:为了使事件处理程序工作,请确保您的非匿名函数(使用defn或let创建)与匿名表单相同,尤其是参数列表.

onClick未定义,因为您使用它就好像它是一个Om协议.有关正确使用,请参阅Om生命周期协议.

https://github.com/swannodette/om/wiki/Documentation