为什么我发表评论时,子组件中的计数器更新正常
(om/update-state! owner :clicked not)
而不是在我在下面的代码中的父组件中取消注释它? 单击按钮即可更新计数器。
我想要实现的是一个发布/订阅机制,因此组件可以以分离的方式交换消息。
您可以通过以下方式创建一个新项目来复制它:
lein new mies-om om-channel-test
然后用下面的代码替换core.cljs并运行
lein cljsbuild auto
在现代浏览器中访问index.html页面(例如最新的Chrome)。
代码:
(ns om-channel-test.core
(:require-macros [cljs.core.async.macros :refer (go)])
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[cljs.core.async :refer [chan pub <! sub >! timeout put!]]))
(enable-console-print!)
(def app-state (atom {:text "Hello world!"}))
(def event-ch (chan))
(def event-pub
(pub event-ch #(:topic %)))
(defn child [cursor owner]
(reify
om/IInitState
(init-state [_]
{:counter 0})
om/IWillMount
(will-mount [_]
(go (loop [] (<! (om/get-state owner :subscriber))
(println "message received")
(om/update-state! owner :counter inc)
(recur))))
om/IRender
(render [_]
(println "rendering child")
(dom/p nil (om/get-state owner :counter)))
om/IWillUnmount
(will-unmount [_]
(println "unmount"))))
(defn parent [cursor owner]
(om/component
(println "rendering parent")
(dom/div nil
(dom/button #js {:onClick
#(do
#_(om/update-state! owner :clicked not)
(go (>! event-ch {:topic :wizard
:message "hello"})))}
"Click")
(om/build child
cursor
{:init-state
{:subscriber
((om/get-shared owner :create-subscriber) :wizard)}}))))
(om/root
parent
app-state
{:target (. js/document (getElementById "app"))
:shared {:create-subscriber (fn [topic]
(sub event-pub
topic (chan)))
:event-ch event-ch}})
答案 0 :(得分:0)
回答https://groups.google.com/forum/#!topic/clojurescript/5rCTfnulNXI。
如果第41行未注释,则会发生以下情况:
父组件的状态已更改
om/react
“遍历”父级渲染中的组件树以查看应更新的内容
om/build
的第45行发现子组件已经存在,因此没有创建或安装新组件。
但是,第45行的“正在运行”/致电om/build
在event-pub
:subscriber/:create-subscriber
到{:init-state ...}
的新订阅将不会创建一个新组件来创建从这个新订阅者频道使用的循环(对于来自第22行的新组件,没有调用om/will-mount
)
现在event-pub
有两个订阅者,但只有一个go-loop
来自频道。 :event-ch
上的酒吧将阻止[1] [2]
页面上的怪异
似乎你不应该在传递给{:init-state ...}
的{{1}}中产生副作用。而是通过om/build
将event-pub
传递给子组件,并与:init-state
一起创建子chan以从中使用。
[1] http://clojure.github.io/core.async/#clojure.core.async/pub “每个项目并行和同步分配给所有潜艇, 即每个子必须在下一个项目分发之前接受。使用 缓冲/开窗以防止缓慢的潜水员阻止酒吧。“
[2]在第57行的chan中进行缓冲,以便在几次点击中看到此行为更改