W małej aplikacji Jestem budynku, który używa odczynników i Re-rama Używam multi-metody wysyłką która strona powinna być wyświetlane na podstawie wartości w stanie aplikacji:Dlaczego multi-metody nie działają jako funkcje dla odczynnika/ponownej ramki?
(defmulti pages :name)
(defn main-panel []
(let [current-route (re-frame/subscribe [:current-route])]
(fn []
;...
(pages @current-route))))
a potem mają metody takie jak:
(defmethod layout/pages :register [_] [register-page])
gdzie funkcja register-page
wygeneruje rzeczywisty widok:
(defn register-page []
(let [registration-form (re-frame/subscribe [:registration-form])]
(fn []
[:div
[:h1 "Register"]
;...
])))
próbowałem changing my app so that the methods generated the pages directly, jak w:
(defmethod layout/pages :register [_]
(let [registration-form (re-frame/subscribe [:registration-form])]
(fn []
[:div
[:h1 "Register"]
;...
])))
i to spowodowało, że żadna strona nie zostanie wyświetlona. Moim głównym panelu I changed the call to pages
to square brackets tak, że odczynnik będzie miał wgląd w to:
(defn main-panel []
(let [current-route (re-frame/subscribe [:current-route])]
(fn []
;...
[pages @current-route])))
i który spowodował pierwszy odwiedził stronę do pracy, ale po tym, klikając na linki (co powoduje, że prąd drogę do zmiany) nie ma efekt.
Wszystkie obszary nazw definiujące poszczególne metody są wymagane w pliku, który jest załadowany jako pierwszy, zawiera funkcję init, a fakt, że mogę wybrać jedną stronę i wyświetlić ją, dowodzi, że kod ładuje się (następnie przełączanie aby inna strona nie działa):
https://github.com/carouselapps/ninjatools/blob/master/src/cljs/ninjatools/core.cljs#L8-L12
W celu debugowania, co się dzieje, ja zdefiniowane dwie trasy, :about
i :about2
, jeden jako funkcję i jedną jako metoda:
(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."]))
i utworzyłem układ wydruku wyniku wywołania pages
(musiał użyć połączenia jawnego zamiast nawiasów kwadratowych oczywiście). Zawinięty funkcja, ten, który działa, zwraca:
[#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);
});
}"]]
natomiast metoda zwraca:
#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);
}"]
Gdybym zmienić metodę być:
(defmethod layout/pages :about2 [_]
[(fn []
[:div "This is the About 2 Page."])])
czyli zawracania funkcja w wektorze, a następnie zaczyna działać. A jeśli robię odwrotną zmianę funkcji zapakowane, zaczyna się nie w ten sam sposób, co w sposobie:
(defn about-page []
(fn []
[:div "This is the About Page."]))
(defmethod layout/pages :about [_]
about-page)
sprawia trochę sensie jak składnia odczynnik jest [function]
ale miało to automatycznie wywołać funkcję .
zacząłem też wyprowadzanie @current-route
do przeglądarki, na przykład:
[:main.container
[alerts/view]
[pages @current-route]
[:div (pr-str @current-route)]]
i zweryfikowane @current-route
jest modyfikowany poprawnie i wyjście aktualizowane, po prostu nie [pages @current-route]
.
pełny kod źródłowy dla mojej aplikacji można znaleźć tutaj: https://github.com/carouselapps/ninjatools/tree/multi-methods
Update: corrected the arity of the methods following Michał Marczyk's answer.
Czy potrzebujesz przestrzeni nazw, w której używasz 'defmethod' w jakiejś root przestrzeni nazw? Ponieważ, jeśli nie potrzebujesz jawnie tych przestrzeni nazw, twoje metody po prostu nie zostaną dodane do multimetra. – skrat
@skrat tak. Będę edytować pytanie, aby to zauważyć. – Pablo
Do debugowania tego chciałbym 1. Dodaj domyślną metodę i 2. wydrukować, co multimethod powraca (prawdopodobnie zero). – PeakCode