LoginSignup
7
6

More than 5 years have passed since last update.

ElmのSPAへの第一歩のNavigation

Last updated at Posted at 2017-12-24

 Elmはシンプルで素晴らしんだけど、ドキュメントが弱い気がします。このブログでは、初心者の私がいろいろなソースを見つけて備忘録を付けています。そこで他のJavaScriptライブラリのようにRouterを使いたいと思い、とりあえずNavigationにたどり着きました。
http://package.elm-lang.org/packages/elm-lang/navigation/latest/Navigation

 通常のHtmlではリンク(aタグ)をクリックしたときに、通常のように別ページを読み込むためのリクエストをサーバに送り、別ページに遷移します。Navigationはこの動作を、Msgを発行してupdate関数を呼ぶように変更します。以下がサンプルです。
https://github.com/elm-lang/navigation/tree/master/examples

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Navigation


main =
  Navigation.program UrlChange
    { init = init
    , view = view
    , update = update
    , subscriptions = (\_ -> Sub.none)
    }


-- MODEL
type alias Model =
  { history : List Navigation.Location
  }


init : Navigation.Location -> ( Model, Cmd Msg )
init location =
  ( Model [ location ]
  , Cmd.none
  )


-- UPDATE
type Msg
  = UrlChange Navigation.Location

{- We are just storing the location in our history in this example, but
normally, you would use a package like evancz/url-parser to parse the path
or hash into nicely structured Elm values.

    <http://package.elm-lang.org/packages/evancz/url-parser/latest>

-}
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    UrlChange location ->
      ( { model | history = location :: model.history }
      , Cmd.none
      )


-- VIEW
view : Model -> Html msg
view model =
  div []
    [ h1 [] [ text "Pages" ]
    , ul [] (List.map viewLink [ "bears", "cats", "dogs", "elephants", "fish" ])
    , h1 [] [ text "History" ]
    , ul [] (List.map viewLocation model.history)
    ]

viewLink : String -> Html msg
viewLink name =
  li [] [ a [ href ("#" ++ name) ] [ text name ] ]


viewLocation : Navigation.Location -> Html msg
viewLocation location =
  li [] [ text (location.pathname ++ location.hash) ]

 まず次の宣言ですが、これで画面上でURLリンクをクリックしたときに UrlChange Navigation.Location のMsgを発行してくれるようになります。

main =
  Navigation.program UrlChange
    { init = init
    , view = view
    , update = update
    , subscriptions = (\_ -> Sub.none)
    }

念のためにprogram関数の型をあげておきます。

program
    :  (Location -> msg)
    -> { init : Location -> (model, Cmd msg), update : msg -> model -> (model, Cmd msg), view : model -> Html msg, subscriptions : model -> Sub msg }
    -> Program Never model msg

 Msgを受け取ったupdateはmodelのリストにlocationを追加します。追加のコードは以下です。

 { model | history = location :: model.history }

 これは見易いようにカッコを付けると以下のようになります。

 { model | history = (location :: model.history) }

 このプログラムを実行すると"bears", "cats", "dogs"などのリンクが表示されますので、それらをクリックすると、以下のようにlocation.pathname ++ location.hashを表示するものです。例えば、path="/examples/Example.elm"、hash="#dogs"となっています。

History
/examples/Example.elm#dogs
/examples/Example.elm#cats
/examples/Example.elm#bears
/examples/Example.elm

 プログラム中のコメントは次のように言っています。つまり、ここではlocationはただ単にそのままリストに蓄えていっているけれども、普通はpathnameやhashの文字列をparseして、Elmの構造化された値に変換します。evancz/url-parserというElm作者の作ったパッケージが使われます。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6