最近试着使用shadow-cljs和reagent开发web前端,一起步马上发现reagent好像没有提供路由模块,试着自己简单实现了一个
通过几行代码实现了router模块
(ns app.utils.route
(:require [reagent.core :refer [atom]]
[app.utils.string :refer [str-eq?]]))
(defn push-state [path] (.pushState js/history {} "" (str "#" path)))
(defn replace-state [path] (.replaceState js/history {} "" (str "#" path)))
(defn get-location []
(let [hash (.-hash js/location)]
{:hash hash
:name (apply str (rest hash))}))
(defonce location-state (atom (get-location)))
(js/addEventListener "hashchange"
#(reset! location-state
(get-location)))
(defn render-router [items name]
(let [show (filter #(str-eq? name
(:name %))
items)]
(if (empty? show)
[:div]
[(:page (first show))])))
(defn router [{:keys [default] :or {default "main"}} & args]
(let [name (:name @location-state)]
(if (empty? name)
(do
(replace-state default)
(render-router args default)
)
(render-router args name))))
使用方式
(ns app.core
(:require [reagent.core :as r]
[app.utils.route :as route]
[app.page.main :as main-page]
[app.page.list :as list-page]))
(defn ^:dev/after-load start
[]
(r/render-component
[route/router
:default "main"
{:name "main" :page main-page/view}
{:name "list" :page list-page/view}
]
(.getElementById js/document "app")))
(defn ^:export main
[]
(start))