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



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

我在榆树有一个视图,返回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 个左右的操作(。

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

我正在设想许多嵌套子组件可能希望能够动态调用父组件的任何操作而无需硬编码的场景,这就是我决定仍然提出这个问题的原因。

谢谢。

你肯定想多了!这样做的方式是

-- 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
]

最新更新