在我正在构建的一个使用 Reagent 和 Re-frame 的小型应用程序中,我使用多种方法来调度应该根据应用程序状态中的值显示哪个页面:
(defmulti pages :name)
(defn main-panel []
(let [current-route (re-frame/subscribe [:current-route])]
(fn []
;...
(pages @current-route))))
然后我有如下方法:
(defmethod layout/pages :register [_] [register-page])
该register-page
函数将生成实际视图的位置:
(defn register-page []
(let [registration-form (re-frame/subscribe [:registration-form])]
(fn []
[:div
[:h1 "Register"]
;...
])))
我尝试更改我的应用程序,以便方法直接生成页面,如下所示:
(defmethod layout/pages :register [_]
(let [registration-form (re-frame/subscribe [:registration-form])]
(fn []
[:div
[:h1 "Register"]
;...
])))
这导致没有页面被渲染。在我的主面板中,我将调用更改pages
为方括号,以便 Reagent 可以看到它:
(defn main-panel []
(let [current-route (re-frame/subscribe [:current-route])]
(fn []
;...
[pages @current-route])))
这会导致第一个访问的页面正常工作,但在那之后,单击链接(导致当前路由更改)没有任何效果。
在首先加载的文件中需要定义各个方法的所有命名空间,该文件包含 init 函数,并且我可以选择任何单个页面并显示它的事实证明代码正在加载(然后,切换到另一个页面不会不工作):
https://github.com/carouselapps/ninjatools/blob/master/src/cljs/ninjatools/core.cljs#L8-L12
为了调试正在发生的事情,我定义了两条路线,:about
并且:about2
,一条作为函数,一条作为方法:
(defn about-page []
(fn []
[:div "This is the About Page."]))
(defmethod layout/pages :about [_]
[about-page])
(defmethod layout/pages :about2 [_]
(fn []
[:div "This is the About 2 Page."]))
并使布局打印调用的结果pages
(当然必须使用显式调用而不是方括号)。包装的函数,一个有效的函数,返回:
[#object[ninjatools$pages$about_page "function ninjatools$pages$about_page(){
return (function (){
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [new cljs.core.Keyword(null,"div","div",1057191632),"This is the About Page."], null);
});
}"]]
而方法返回:
#object[Function "function (){
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [new cljs.core.Keyword(null,"div","div",1057191632),"This is the About 2 Page."], null);
}"]
如果我将方法更改为:
(defmethod layout/pages :about2 [_]
[(fn []
[:div "This is the About 2 Page."])])
也就是说,在向量中返回函数,然后它开始工作。如果我对包装函数进行反向更改,它会以与方法相同的方式开始失败:
(defn about-page []
(fn []
[:div "This is the About Page."]))
(defmethod layout/pages :about [_]
about-page)
像 Reagent 的语法一样有点道理,[function]
但它应该自动调用该函数。
我也开始输出@current-route
到浏览器,如下所示:
[:main.container
[alerts/view]
[pages @current-route]
[:div (pr-str @current-route)]]
并且我验证@current-route
正在正确修改并且输出更新,只是没有[pages @current-route]
。
我的应用程序的完整源代码可以在这里找到:https ://github.com/carouselapps/ninjatools/tree/multi-methods