将多个复杂的父操作传递给深层嵌套的子视图

问题描述 投票:0回答:1

免责声明:我写完后意识到这是一个愚蠢的问题。请不要花太多时间阅读它。我对Elm,函数式编程非常陌生,而不是UI爱好者。

我在Elm中有一个视图,该视图返回Html Msg并接受model。以简单的增量演示为例,我有以下典型设置:

module Main exposing (..)
import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)
-- MAIN

main =
  Browser.sandbox { init = init, update = update, view = view }

-- MODEL
type alias Model = Int

init : Model
init =
  0

-- UPDATE
type Msg
  = Increment
  | Decrement

update : Msg -> Model -> Model
update msg model =
  case msg of
    Increment ->
      model + 1

    Decrement ->
      model - 1

-- VIEW

view : Model -> Html Msg
view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (String.fromInt model) ]
    , button [ onClick Increment ] [ text "+" ]
    ]

我有一个非常复杂的按钮组件,我想将其提取到一个单独的函数中。我可以使用普通HTML来做到这一点,即

-- VIEW
some_html : Html msg
some_html =
  text "FOO"

view : Model -> Html Msg
view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (String.fromInt model) ]
    , button [ onClick Increment ] [ text "+" ]
    , some_html
    ]

我还可以传递我定义的Msg类型,并让“子功能”调用操作:

-- VIEW
make_button : Msg -> Html Msg
make_button msg =
  button [ onClick msg ] [ text "-" ]

view : Model -> Html Msg
view model =
  div []
    [ make_button Decrement
    , div [] [ text (String.fromInt model) ]
    , button [ onClick Increment ] [ text "+" ]
    ]

我的问题是:

我希望能够使我的make_button函数能够处理多个动作。我发现可行的一种方法是先通过所有可能的操作,然后再通过一个密钥,即

-- VIEW
make_button : Msg -> Msg -> String -> Html Msg
make_button decr incr which =
  if which == "Decrement" then
  button [ onClick decr ] [ text "-" ]
  else button [ onClick incr ] [ text "+" ]

view : Model -> Html Msg
view model =
  div []
    [ make_button Decrement Increment "Decrement"
    , div [] [ text (String.fromInt model) ]
    , make_button Decrement Increment "Increment" -- doesn't matter here.
    ]

但是当动作数量很大(在我的用例中,我有20个左右的动作)时,这变得很麻烦。

我应该创建各种字典吗?有没有办法做到这一点?这是一件坏事吗?请给我悲伤。

我正在想象这样的场景,其中许多嵌套的子组件可能希望能够在不进行硬编码的情况下即时调用父组件的任何Action,这就是为什么我决定仍然问这个问题的原因。

谢谢。

elm
1个回答
0
投票

您肯定是在考虑问题!您执行此操作的方式是

-- camel case is the convention in Elm ;)
makeButton : Msg -> Html Msg
makeButton msg =
    button
        [ onClick msg ]
        [ text <|
            -- an if statement would also work in this case
            case msg of
                Increment ->
                    "+"

                Decrement ->
                    "-"
        ]


view : Model -> Html Msg
view model =
    div []
        [ makeButton Decrement
        , div [] [ text (String.fromInt model) ]
        , makeButton Increment
        ]
© www.soinside.com 2019 - 2024. All rights reserved.