我目前正在尝试学习 om.next 。
这是我的代码:
(ns hlearn.core
(:require [goog.dom :as gdom]
[om.next :as om :refer-macros [defui]]
[om.dom :as dom]
[sablono.core :as html :refer-macros [html]]))
(enable-console-print!)
(def app-data
(atom {:user ""
:main-menu {:selected :home}}))
;; -------------------------------------------------------------------------
;; Parsing
(defmulti read om/dispatch)
(defmethod read :selected
[{:keys [state]} _ _]
{:value (get-in @state [:main-menu :selected])})
;; -------------------------------------------------------------------------
;; Components
(defui MainMenu
static om/IQuery
(query [this]
[:selected])
Object
(render [this]
(let [{:keys [selected]} (om/props this)]
(println (= selected :home)))))
(def main-menu (om/factory MainMenu))
(defui RootView
Object
(render [this]
(println "Render RootView")
(main-menu)))
(def reconciler
(om/reconciler
{:state app-data
:parser (om/parser {:read read})}))
(om/add-root! reconciler
RootView (gdom/getElement "app"))
我的目标是组件MainMenu
必须在控制台上编写true
(目前正在编写false
)。
由于read函数应返回{:value :home}
(app-state的值),因此(= selected :home)
应为true。
实际上,MainMenu
在控制台上写false
,因为selected
的值为nil
。
答案 0 :(得分:2)
事实证明,RootView
上呈现的(om/add-root!)
组件必须为所有应用程序提供查询。
在这种情况下,RootView
也必须提供查询,并将selected
密钥传递给MainMenu
组件。
(def app-data
(atom {:user ""
:menu {:selected :home}}))
(defui RootView
static om/IQuery
(query [this]
`[{:menu (om/get-query MainMenu)}])
Object
(render [this]
(let [{:keys [menu]} (om/props this)]
(println "Render RootView")
(main-menu menu))))
此外,阅读器功能会调度:menu
键,而不是:selected
键。
(defmethod read :menu
[{:keys [state]} _ _]
{:value (get-in @state [:menu])})
其余代码保持不变。
答案 1 :(得分:1)
在om.next
中,正如您所发现的,所有查询都必须组成根组件。根据{{1}}函数在处理根查询时返回的内容,为根组件分配其props
。
如果任何子组件有查询,则该查询请求的props应该作为子组件的工厂方法的第一个参数传递。这是你失踪的第二件。
如果您查询子组件中最终未被其父组件传递的内容,则Om中目前没有任何警告或错误。因此,如果您忘记传递道具,最终会为子组件中的键解构read
值。