我正在尝试使用om.next,尝试扩展Components, Identity & Normalization中给出的示例。
上面链接的示例中的代码包含两个列表,这些列表由状态中两个不同路径中的数据支持。该示例显示了数据规范化如何使得可以轻松更新在不同视图中出现的规范化实体。在下面的代码中,我删除了下面示例中的第二个列表,因为无论如何都会出现行为。
以下示例有效并显示:
其中+是一个增加人物点数的按钮。
(ns ui.core
(:require [om.next :as om :refer-macros [defui]]
[om.dom :as dom]
[goog.dom :as gdom]))
(def init-data
{:list/one [{:name "John" :points 0}
{:name "Mary" :points 0}
{:name "Bob" :points 0}]})
;; -----------------------------------------------------------------------------
;; Parsing
(defmulti read om/dispatch)
(defn get-people [state key]
(let [st @state]
(into [] (map #(get-in st %)) (get st key))))
(defmethod read :list/one
[{:keys [state] :as env} key params]
{:value (get-people state key)})
(defmulti mutate om/dispatch)
(defmethod mutate 'points/increment
[{:keys [state]} _ {:keys [name]}]
{:action
(fn []
(swap! state update-in
[:person/by-name name :points]
inc))})
;; -----------------------------------------------------------------------------
;; Components
(defui Person
static om/Ident
(ident [this {:keys [name]}] [:person/by-name name])
static om/IQuery
(query [this] '[:name :points :age])
Object
(render [this]
(let [{:keys [points name] :as props} (om/props this)]
(dom/li nil
(dom/label nil (str name ", points: " points))
(dom/button
#js {:onClick
(fn [e]
(om/transact! this
`[(points/increment ~props)]))}
"+")))))
(def person (om/factory Person {:keyfn :name}))
(defui ListView
Object
(render [this]
(let [list (om/props this)]
(apply dom/ul nil
(map person list)))))
(def list-view (om/factory ListView {:key-fn ffirst}))
(defui RootView
static om/IQuery
(query [this]
(let [subquery (om/get-query Person)]
`[{:list/one ~subquery}]))
Object
(render [this]
(let [{:keys [list/one]} (om/props this)]
(apply dom/div nil
[
(dom/h2 nil "List A")
(list-view one)
]))))
(def rootview (om/factory RootView))
;; wrapping the Root in another root (this fails)
(defui AnotherRoot
static om/IQuery
(query [this] `[~@(om/get-query RootView)])
Object
(render
[this]
(dom/div nil
(rootview (om/props this)))))
(def reconciler
(om/reconciler
{:state init-data
:parser (om/parser {:read read :mutate mutate}) }))
(om/add-root! reconciler RootView (gdom/getElement "app"))
但是,当我将最后一行中的RootView更改为AnotherRoot时,如:
(om/add-root! reconciler AnotherRoot (gdom/getElement "app"))
ui仍然呈现,但是当按下按钮时,会发生以下错误:
Error: No queries exist for component path
(ui.core/AnotherRoot ui.core/RootView ui.core/Person)
错误来自(next.cljc:1916)
我不理解错误。来自AnotherRoot
的查询返回与RootView
相同的查询(但是,当您立即返回查询时,您会收到警告 - 这很有意义),但协调程序似乎无法弄清楚当app-state改变时如何重新渲染组件。
相关的依赖应该是:
[[org.clojure/clojure "1.9.0-alpha14"]
[org.clojure/clojurescript "1.9.473"]
[figwheel-sidecar "0.5.9"]
[org.omcljs/om "1.0.0-alpha47"]]
在om.next中创建嵌套组件的一般方法是什么?