在你的codebase還不太大的狀況之下,其實不太需要這個delegation。我目前只有在frontend master裡的 elm in action
course上,聽Richard Feldman講過這個。其他地方(我google過了)都沒有講這個概念。如果你想要學好elm的話,推薦他這個課程。至於書本目前只有出到第六章而已(目前不推薦)。
因為elm workshop的 code 是在github上的,我就直接拿來講解,有興趣的可以看整個code。
type alias Model =
{ query : String
, results : List SearchResult
, errorMessage : Maybe String
, minStars : Int
, minStarsError : Maybe String
, searchIn : String
, userFilter : String
}
這樣的話,Model 會越來越大,越來越大,如果你想要refactor 的話,要怎麼做呢? 你可以寫一個 type alias
type alias Model =
{ query : String
, results : List SearchResult
, errorMessage : Maybe String
, options : SearchOptions
}
type alias SearchOptions =
{ minStars : Int
, minStarsError : Maybe String
, searchIn : String
, userFilter : String
}
這樣是不是輕爽多了?但隨著code變多,你的 update
要監聽的動作也會變多,所以 Msg
也會越來越長,越來越無法控制,怎麼辦?
type Msg
= Search
| SetQuery String
| DeleteById Int
| HandleSearchResponse (List SearchResult)
| HandleSearchError (Maybe String)
| DoNothing
| SetMinStars String
| SetSearchIn String
| SetUserFilter
-- 多了三個和search有關的
沒錯,你也學起來了,再用另外一個 type
包裝一下:
type Msg
= Search
| SetQuery String
| DeleteById Int
| HandleSearchResponse (List SearchResult)
| HandleSearchError (Maybe String)
| DoNothing
| Options OptionsMsg
type OptionsMsg
= SetMinStars String
| SetSearchIn String
| SetUserFilter
這樣就好了!?
事情還沒完,因為這樣子你的view也會不一樣啊~~ 本來的 viewOptions : Model -> Html Msg
,現在要改成:viewOptions : SearchOptions -> Html OptionsMsg
但是我們的view 呢? view: Model -> Html Msg
可是我們的 viewOptions
是給出 Html OptionsMsg
type。怎麼辦?好像越改越慘?
還記得 List.map String.length ["hello", "world"]
怎麼作用嗎?就是把 List內的String
變成Int。同樣的,Elm很多地方都有提供這個 map
讓你可以變換內部的type。
List.map Html.map Cmd.map Sub.map
我們看看 Html.map: (a -> msg) -> Html a -> Html msg
所以我們的code可以改寫成:
-- inside the view function:
Html.map Options (viewOptions model.options)
Options
是我們內建在 type Msg
裡的,可以把 OptionsMsg -> Msg
這樣子,在code越來越多、越來越大,就可以用這種方式來refactor 本來的code!