在开始这个问题之前,我会说在 Clojure/Script 方面我仍然是一个新手,所以除了非常尖锐的问题之外,我将提出关于样式的任何一般性反馈,非常感谢使用。
我一直在用 om.next 构建一个非常简单的应用程序。对于客户端路由,我决定使用秘书。我的应用程序显示一个项目列表,目的是当您单击其中一个项目时,您可以查看详细信息。目前的实现是通过一个简单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}))
精明的人会发现我正在尝试使用 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
)。最让我困惑的是,如果我app-state
在 REPL 中手动执行相同的查询,我会得到正确的数据集......
(get-in @app-state [:items/by-id 1])
; {:id 1, :title "stack overflow", :description "hello, world.", :photos []}
到目前为止,唯一对我有用的是绕过协调器(自己创建组件实例),将查询值app-state
作为道具传递。但这意味着我不能通过调和器来改变状态,这是一个新的可怕的皱纹,对一个原本凌乱、蓬乱的难题来说是一个新的可怕的皱纹。
我在这里想念什么?虽然我有很多想法,但我最怀疑的是app-state
via的初始化om/tree->db
。