我覺得routing用文字來描述有他的極限,但我又懶得畫圖(因為一天要寫一篇,還要畫圖真是強人所難啊…),建議大家下載這個專案,就是要來介紹elm的routing system的。如果你想要自己做一個elm 的 single page app,就有需要啦。在大計畫開始前,先來做做這個小小的專案吧。
git clone https://github.com/sporto/elm-navigation-pushstate-example.git
先認識這兩個套件,如果你要做routing 的話,一個是 Navigation, 另一個是UrlParser
有好工具才好工作,在Navigation裡,會有個 Html.program
來取代原本的Html.program,才可以監聽是不是有location改變。
Same as Html.program, but your update function gets messages whenever
the URL
changes.
也就是說Navigation裡的update會幫你聽聽看有沒有位置改變,有的會也會重新render整個view。
type alias Location = { href : String , host : String , hostname : String , protocol : String , origin : String , port_ : String , pathname : String , search : String , hash : String , username : String , password : String }
你看,裡面還有一個叫Location的type alias,會放在 Html.program
裡的第一個parameter:
(Location -> msg), 當有位置改變,會去call elm-runtime 再去call
update。
可以看在elm-tutorial
裡的圖:
initial:
when updating:
我們也不是大神,有神人寫好的例子,我們直接拿來用。再用之前,我們來讀讀code:
main : Program Never Model Msg
main =
Navigation.program OnLocationChange
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
program會一直用 OnLocationChange
來監聽有沒有改變,如果會就會送出 location
的訊息給 update
function
type Msg
= ChangeLocation String
| OnLocationChange Navigation.Location
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ChangeLocation path ->
( { model | changes = model.changes + 1 }, Navigation.newUrl path )
OnLocationChange location ->
let
newRoute =
parseLocation location
in
( { model | route = newRoute }, Cmd.none )
當 update function 收到後,就會去parse url,這時候就是UrlParser的作用了:
matchers : UrlParser.Parser (Route -> a) a
matchers =
UrlParser.oneOf
[ UrlParser.map HomeRoute UrlParser.top
, UrlParser.map AboutRoute (UrlParser.s "about")
]
parseLocation : Navigation.Location -> Route
parseLocation location =
case (UrlParser.parsePath matchers location) of
Just route ->
route
Nothing ->
NotFoundRoute
詳細的介紹,我推薦看UrlParser的doc但常用的 oneOf
, map
, top
, s
這個例子都有用上了。其實不難理解,而且很快就可以上手,如果再不懂可以用elm-reactor,的debug工具,看他送出什麼訊息,研究一下就可以上手了。明天再來說說這些除錯工具好了。