我将在这个问题的前言中说我在Clojure / Script方面仍然是一个新手,所以除了非常尖锐的问题,我将提出关于风格的任何一般性反馈,我将非常感激使用。
我用om.next构建了一个非常简单的应用程序。对于客户端路由,我决定使用Secretary。我的应用程序显示项目列表,目的是当您单击其中一个项目时,您可以查看详细信息。目前的实现是通过锚标记上的简单href
(例如,href
可能看起来像/items/1
,其中1
是id
)。部分原因是您应该能够直接导航到详细信息URL以查看相同的视图。就像这听起来一样简单,我不能为我的生活让这个按照需要工作。
首先,让我们看看协调程序的显着配置(为简洁起见,我已经删除了整个组件render
的实现细节)......
(def init-data {:items [{:id 1
:title "stack overflow"
:description "hello, world."
:photos []}
{:id 2
:title "foo"
:description "bar"
:photos []}]})
(defui ListItem
static om/Ident
(ident [this {:keys [id]}]
[:items/by-id id])
static om/IQuery
(query [this]
[:id :title :description :photos]))
(defui Items
static om/IQuery
(query [this]
[{:items (om/get-query ListItem)}]))
(defmulti read om/dispatch)
(defmethod read :items
[{:keys [state query] :as env} key _]
(let [st @state]
{:value (om/db->tree query (get st key) st)}))
(def app-state (atom (om/tree->db Items init-data true)))
(def reconciler
(om/reconciler {:parser (om/parser {:read read})
:state app-state}))
精明的人会看到我正在努力think with links,这似乎正如我所期望的那样起作用。当我添加这个组件,并尝试在秘书路线后面使用它时,一切都崩溃了......
; I tried other approaches, they failed too
(defui Item
static om/IQueryParams
(params [this]
{:id :not-found})
static om/IQuery
(query [this]
'[[:items/by-id ?id]]))
(defn render-component [component]
(let [app (gdom/getElement "app")]
(doto reconciler
(om/remove-root! app)
(om/add-root! component app)))))
(defroute item-path "/items/:id" [id]
(let [component Item]
; this is already less than ideal, as we know the id
; before the first render of the component
(render-component component)
(om/set-query! (om/class->any reconciler component)
{:id (js/parseInt id)})))
我的Item
组件的实例未在props
中收到查询中指定的正确状态(它接收整个app-state
)。最令我困惑的是,如果我在REPL中手动对app-state
执行相同的查询,我会得到正确的数据集......
(get-in @app-state [:items/by-id 1])
; {:id 1, :title "stack overflow", :description "hello, world.", :photos []}
到目前为止,对我来说唯一有用的是绕过协调程序(自己创建组件实例),将app-state
的查询值作为道具传递。但这意味着我不能通过调和来改变状态,这是一个新的可怕的皱纹,而不是一个混乱,不整洁的难题。
我在这里缺少什么?虽然我有很多想法,但我最怀疑的是通过app-state
初始化om/tree->db
。