本頁包含 Elm 0.18

組合

父元件

下列為父元件程式碼。

module Main exposing (..)

import Html exposing (Html, program)
import Widget


-- MODEL


type alias AppModel =
    { widgetModel : Widget.Model
    }


initialModel : AppModel
initialModel =
    { widgetModel = Widget.initialModel
    }


init : ( AppModel, Cmd Msg )
init =
    ( initialModel, Cmd.none )



-- MESSAGES


type Msg
    = WidgetMsg Widget.Msg



-- VIEW


view : AppModel -> Html Msg
view model =
    Html.div []
        [ Html.map WidgetMsg (Widget.view model.widgetModel)
        ]



-- UPDATE


update : Msg -> AppModel -> ( AppModel, Cmd Msg )
update message model =
    case message of
        WidgetMsg subMsg ->
            let
                ( updatedWidgetModel, widgetCmd ) =
                    Widget.update subMsg model.widgetModel
            in
                ( { model | widgetModel = updatedWidgetModel }, Cmd.map WidgetMsg widgetCmd )



-- SUBSCRIPTIONS


subscriptions : AppModel -> Sub Msg
subscriptions model =
    Sub.none



-- APP


main : Program Never AppModel Msg
main =
    program
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }

細察程式碼重要的部份。

模型

type alias AppModel =
    { widgetModel : Widget.Model ➊
    }

父元件也有自己的模型。模型內的一個屬性容納 Widget.Model ➊。注意到父元件並不清楚 Widget.Model 是什麼。

initialModel : AppModel
initialModel =
    { widgetModel = Widget.initialModel ➋
    }

當應用程式建立初始的模型時,只簡單呼叫 Widget.initialModel ➋ 即可。

若有多個子元件,依樣畫葫蘆,如:

initialModel : AppModel
initialModel =
    { navModel = Nav.initialModel,
    , sidebarModel = Sidebar.initialModel,
    , widgetModel = Widget.initialModel
    }

或者,當多個子元件為相同型別:

initialModel : AppModel
initialModel =
    { widgetModels = [Widget.initialModel]
    }

訊息

type Msg
    = WidgetMsg Widget.Msg

使用聯集型別包裝 Widget.Msg,標示為該元件的訊息。這讓應用程式得以轉送訊息到相關元件(看更新函式會清楚一些)。

若應用程式有多個子元件時,可以像這樣做:

type Msg
    = NavMsg Nav.Msg
    | SidebarMsg Sidebar.Msg
    | WidgetMsg Widget.Msg

視界

view : AppModel -> Html Msg
view model =
    Html.div []
        [ Html.map➊ WidgetMsg➋ (Widget.view➌ model.widgetModel➍)
        ]

主應用程式 view 轉譯 Widget.view ➌。但是 Widget.view 發出的是 Widget.Msg,跟目前視界發出的 Main.Msg 並不相容。

  • 使用 Html.App.map ➊ 將 Widget.view 發出的訊息映射到預期的(Msg)。Html.App.map 將來自於子視界訊息加上 WidgetMsg ➋ 標籤
  • 只傳遞子元件所關心的部份模型進去,換言之就是 model.widgetModel ➍。

更新

update : Msg -> AppModel -> (AppModel, Cmd Msg)
update message model =
    case message of
        WidgetMsg➊ subMsg➋ ->
            let
                (updatedWidgetModel, widgetCmd)➍ =
                    Widget.update➌ subMsg model.widgetModel
            in
                ({ model | widgetModel = updatedWidgetModel }, Cmd.map➎ WidgetMsg widgetCmd)

update 收到 WidgetMsg ➊ 時,將會委派給子元件。子元件只會更新它所關心的部份,亦即模型的 widgetModel 屬性。

使用樣式對應將 subMsg ➋ 從 WidgetMsg 之中取出。subMsg 將會是 Widget.update 所預期的型別。

使用 subMsgmodel.widgetModel 呼叫 Widget.update ➌。這會傳回一個 tuple,包含更新後的 widgetModel 及一個命令。

再次使用樣式對應解構來自 Widget.update 的結果 ➍。

最後,將來自 Widget.update 的命令映射成正確的型別。使用 Cmd.map ➎ 及 WidgetMsg 標籤,類似剛剛在視界的處理。

results matching ""

    No results matching ""