Elm视图更新滞后一个消息

Elm视图更新滞后一个消息,elm,Elm,我有以下代码试图使用样式元素滚动我自己的dropMenu实现。我遇到了与style elements包中的菜单实现相同的错误。问题在于,在发送另一条消息之前,视图似乎不会更新消息,这意味着视图总是落后于当前状态一步。我怎样才能避开这件事 type alias Menu = { label : String , group : Group , choices : List Choice , isOpen : Bool , selected : String

我有以下代码试图使用样式元素滚动我自己的dropMenu实现。我遇到了与style elements包中的菜单实现相同的错误。问题在于,在发送另一条消息之前,视图似乎不会更新消息,这意味着视图总是落后于当前状态一步。我怎样才能避开这件事

type alias Menu =
    { label : String
    , group : Group
    , choices : List Choice
    , isOpen : Bool
    , selected : String
    }


type alias Choice =
    { label : String
    , item : Item
    , selected : Bool
    }


type Item
    = Diazepam
    | Lorazepam
    | Midazolam
    | NoneChosen


model : Menu
model =
    { label = "First line agents"
    , group = FirstLine
    , choices =
        [ { label = "Diazepam"
          , item = Diazepam
          , selected = False
          }
        , { label = "Lorazepam"
          , item = Lorazepam
          , selected = False
          }
        , { label = "Midazolam"
          , item = Midazolam
          , selected = False
          }
        ]
    , isOpen = False
    , selected = ""
    }


type Group
    = FirstLine
    | SecondLine
    | ThirdLine
    | FourthLine


menuChoice : Choice -> Element MyStyles variation Msg
menuChoice choice =
        if
            choice.selected
                == False
        then
            el Selection [ onClick (SelectChoice choice) ] (text choice.label)
        else
            el Selected [ onClick NoOp ] (text (choice.label ++ "oogityboogity"))


prepend : List a -> List a -> List a
prepend listA listB =
    List.append listB listA


menuDown : Menu -> Element MyStyles variation Msg
menuDown menu =
    column Content
        []
        (case menu.isOpen of
            True ->
                List.append
                    [ el Header [ onClick CloseMenu ] (text menu.label) ]
                    (List.map
                        (\choice ->
                            menuChoice choice
                        )
                        menu.choices
                    )

            False ->
                [ el Header [ onClick OpenMenu ] (text menu.label) ]
        )


menuUp : Menu -> Element MyStyles variation Msg
menuUp menu =
    column Content
        []
        (case menu.isOpen of
            True ->
                List.append
                    (List.map
                        (\choice ->
                            if choice.label == menu.selected then
                                menuChoice choice
                            else
                                menuChoice choice
                        )
                        menu.choices
                    )
                    [ el SubHead [] (text menu.label) ]

            False ->
                [ el SubHead [] (text menu.label) ]
        )



-- UPDATE --


update : Msg -> Menu -> Menu
update msg menu =
    case msg of
        CloseMenu ->
            { menu | isOpen = False }

        OpenMenu ->
            { menu | isOpen = True }

        SelectChoice choice ->
            markSelected menu choice

        NoOp ->
            menu


type Msg
    = CloseMenu
    | OpenMenu
    | SelectChoice Choice
    | NoOp


markSelected : Menu -> Choice -> Menu
markSelected menu selection =
    let
        newMenu =
            { menu
                | selected = selection.label
                , isOpen = False
                , choices =
                    List.map
                        (\choice ->
                            if choice.label == menu.selected then
                                { choice | selected = True }
                            else
                                { choice | selected = False }
                        )
                        menu.choices
            }
    in
        update NoOp newMenu


view : Menu -> Html.Html Msg
view model =
    Element.viewport stylesheet <| menuDown model


main =
    Html.beginnerProgram
        { model = model
        , update = update
        , view = view
        }
类型别名菜单=
{标签:字符串
,组别:组别
,选项:列表选项
,isOpen:Bool
,所选:字符串
}
类型别名选择=
{标签:字符串
,项目:项目
,入选:布尔
}
类型项
=地西泮
|劳拉西泮
|咪唑安定
|非选择
型号:菜单
模型=
{label=“一线代理”
,组=第一线
,选择=
[{label=“地西泮”
,项目=地西泮
,selected=False
}
,{label=“劳拉西泮”
,项目=劳拉西泮
,selected=False
}
,{label=“咪唑安定”
,项目=咪唑安定
,selected=False
}
]
,isOpen=False
,selected=“”
}
类型组
=一线
|二线
|第三线
|第四线
menuChoice:Choice->Element MyStyles variation Msg
menuChoice选择=
如果
选择
==错误
然后
el选择[onClick(SelectChoice)](text choice.label)
其他的
el Selected[onClick NoOp](text(choice.label++“oogityboogity”))
前置:列表a->列表a->列表a
前置列表A列表B=
List.append listB listA
menuDown:Menu->Element MyStyles variation Msg
菜单下菜单=
栏目内容
[]
(case menu.isOpen of of
正确->
List.append
[el头[onClick CloseMenu](文本菜单.标签)]
(List.map)
(\choice->
menuChoice选择
)
菜单选择
)
错误->
[el标题[onClick OpenMenu](文本菜单.标签)]
)
菜单:菜单->元素MyStyles变体Msg
菜单=
栏目内容
[]
(case menu.isOpen of of
正确->
List.append
(List.map)
(\choice->
如果选择choice.label==menu.selected,则
menuChoice选择
其他的
menuChoice选择
)
菜单选择
)
[el分目[](文本菜单.标签)]
错误->
[el分目[](文本菜单.标签)]
)
--更新--
更新:消息->菜单->菜单
更新消息菜单=
味精案例
关闭菜单->
{menu | isOpen=False}
OpenMenu->
{menu | isOpen=True}
选择选择->
标记所选菜单选项
努普->
菜单
输入味精
=关闭菜单
|开放菜单
|选择选择
|努普
标记选定项:菜单->选择->菜单
标记所选菜单选项=
让
新菜单=
{菜单
|selected=selection.label
,isOpen=False
,选择=
List.map
(\choice->
如果选择choice.label==menu.selected,则
{choice | selected=True}
其他的
{choice | selected=False}
)
菜单选择
}
在里面
更新NoOp新菜单
查看:菜单->Html.Html消息
视图模型=

Element.viewport样式表问题出在
markSelected
函数中。以下是上述函数的内容:

markSelected : Menu -> Choice -> Menu
markSelected menu selection =
    let
        newMenu =
            { menu
                | selected = selection.label
                , isOpen = False
                , choices =
                    List.map
                        (\choice ->
                            if choice.label == menu.selected then
                                { choice | selected = True }
                            else
                                { choice | selected = False }
                        )
                        menu.choices
            }
    in
        update NoOp newMenu
您正在映射这些选项,以便更新它们的
selected
状态。要检查哪一个应为
,请将选项的标签与
菜单进行比较。已选择
。但是
菜单。选中的
是以前的菜单状态,这就是为什么模型似乎反映了一次更新的以前状态

相反,您可以与
选择进行比较

if choice.label == selection.label then
此外,这与该问题无关,但为什么要调用
updatenoop newMenu
?只需返回新菜单

markSelected : Menu -> Choice -> Menu
markSelected menu selection =
    { menu
        | selected = selection.label
        , isOpen = False
        , choices =
            List.map
                (\choice ->
                    if choice.label == selection.label then
                        { choice | selected = True }
                    else
                        { choice | selected = False }
                )
                menu.choices
    }

以下是更新后的Ellie(我还清理了一些
if
语句):

问题在于
标记选中的
函数。以下是上述函数的内容:

markSelected : Menu -> Choice -> Menu
markSelected menu selection =
    let
        newMenu =
            { menu
                | selected = selection.label
                , isOpen = False
                , choices =
                    List.map
                        (\choice ->
                            if choice.label == menu.selected then
                                { choice | selected = True }
                            else
                                { choice | selected = False }
                        )
                        menu.choices
            }
    in
        update NoOp newMenu
您正在映射这些选项,以便更新它们的
selected
状态。要检查哪一个应为
,请将选项的标签与
菜单进行比较。已选择
。但是
菜单。选中的
是以前的菜单状态,这就是为什么模型似乎反映了一次更新的以前状态

相反,您可以与
选择进行比较

if choice.label == selection.label then
此外,这与该问题无关,但为什么要调用
updatenoop newMenu
?只需返回新菜单

markSelected : Menu -> Choice -> Menu
markSelected menu selection =
    { menu
        | selected = selection.label
        , isOpen = False
        , choices =
            List.map
                (\choice ->
                    if choice.label == selection.label then
                        { choice | selected = True }
                    else
                        { choice | selected = False }
                )
                menu.choices
    }

以下是更新后的Ellie(我还清理了一些
if
语句):

快速创建了Ellie(),但无法重现您的问题,或者我没有正确地解决它。看起来视图按预期渲染。感谢Ellie,我今天早上在让它工作时遇到了问题。在此处更新:显示问题所在。如果项目已标记为选中,则背景应为蓝色,如果未选中,则背景应为红色。重新创建错误的顺序:打开菜单->单击项目->菜单关闭->打开菜单->所有项目仍然是红色->单击项目->菜单关闭->打开菜单->第一个选中的项目现在蓝色创建了一个快速的Ellie(),但无法重现您的问题,或者我