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