在基本的 Elm 应用程序中重构更新功能
Refactoring update fuction in a basic Elm app
我最近开始使用 Elm,我 运行 遇到了更新功能的问题。我的目标是分割我的大Main.elm file into multiple smaller files, but to do this I first try to split up the main components into smaller components in the same file. For this I rely heavily on this very informative guide。
拆分模型和初始化(我已经为 DiceRoller 做了)相当简单,对于视图来说也很简单。不幸的是,更新并没有那么多。
目前,它看起来像这样(在 Main.elm 文件的 master 分支中)
type Msg = Change String
| Name String
| Password String
| PasswordAgain String
| Roll
| NewFace Int
| SearchImages
| NewSearchResult (Result Http.Error (List String))
| ChangeTermInput String
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Change newContent ->
({ model | content = newContent }, Cmd.none)
Name name ->
({ model | name = name }, Cmd.none)
Password password ->
({ model | password = password }, Cmd.none)
PasswordAgain password ->
({ model | passwordAgain = password }, Cmd.none)
Roll ->
(model, Random.generate NewFace (Random.int 1 100))
NewFace newFace ->
({ model | diceRoller = { dieFace = newFace} }, Cmd.none)
SearchImages ->
(model, getSearchResult model.termInput)
NewSearchResult (Ok newResult) ->
( { model | termResult = newResult }, Cmd.none )
NewSearchResult (Err _) ->
(model, Cmd.none)
ChangeTermInput term ->
({ model | termInput = term}, Cmd.none)
我设法让它更精致了一点,但这无法编译(另请参阅 this Main.elm in the refactoring branch):
type DiceRollerMsg = Roll
| NewFace Int
type Msg = Change String
| Name String
| Password String
| PasswordAgain String
| MsgForDiceRoller DiceRollerMsg
| SearchImages
| NewSearchResult (Result Http.Error (List String))
| ChangeTermInput String
updateDiceRoller : DiceRollerMsg -> DiceRoller -> DiceRoller
updateDiceRoller msg model =
case msg of
Roll ->
model
NewFace newFace ->
{ model | dieFace = newFace}
updateDiceRollerCmd : Msg -> Cmd Msg
updateDiceRollerCmd msg =
case msg of
Roll ->
Random.generate NewFace (Random.int 1 100)
NewFace newFace ->
Cmd.none
updateCmd : Msg -> Model -> Cmd Msg
updateCmd msg model =
Cmd.batch
[ updateDiceRollerCmd msg
, getSearchResult model.termInput
]
updateModel : Msg -> Model -> Model
updateModel msg model =
case msg of
Change newContent ->
{ model | content = newContent }
Name name ->
{ model | name = name }
Password password ->
{ model | password = password }
PasswordAgain password ->
{ model | passwordAgain = password }
MsgForDiceRoller msg ->
{ model | diceRoller = updateDiceRoller msg model.diceRoller}
SearchImages ->
model
NewSearchResult (Ok newResult) ->
{ model | termResult = newResult }
NewSearchResult (Err _) ->
model
ChangeTermInput term ->
{ model | termInput = term}
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
(updateModel msg model, updateCmd msg model)
由于模式与 DiceRollerMsg 匹配,但它试图匹配 Msg。如果我只是将输入和 return 类型更改为 DiceRollerMsg,我会得到: Function updateDiceRollerCmd
is expecting the argument to be: DiceRollerMsg 但它是:Msg
我也不认为 updateCmd 中的 Cmd.batch 是这里最好的解决方案。
对于制作更好的 Elm 应用程序的任何意见,我都很感激,除了这些问题之外。
您的编译错误源于使用 Msg
作为输入和 updateDiceRollerCmd
的 return 值,而 case 语句使用 DiceRollerMsg
。您可以通过从 MsgForDiceRoller
.
进行模式匹配和映射来修复此功能
updateDiceRollerCmd : Msg -> Cmd Msg
updateDiceRollerCmd msg =
case msg of
MsgForDiceRoller Roll ->
Random.generate NewFace (Random.int 1 100)
|> Cmd.map MsgForDiceRoller
_ ->
Cmd.none
您的视图中还有一个编译错误,您需要将 onClick Roll
更改为 onClick (MsgForDiceRoller Rool)
我最近开始使用 Elm,我 运行 遇到了更新功能的问题。我的目标是分割我的大Main.elm file into multiple smaller files, but to do this I first try to split up the main components into smaller components in the same file. For this I rely heavily on this very informative guide。
拆分模型和初始化(我已经为 DiceRoller 做了)相当简单,对于视图来说也很简单。不幸的是,更新并没有那么多。
目前,它看起来像这样(在 Main.elm 文件的 master 分支中)
type Msg = Change String
| Name String
| Password String
| PasswordAgain String
| Roll
| NewFace Int
| SearchImages
| NewSearchResult (Result Http.Error (List String))
| ChangeTermInput String
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Change newContent ->
({ model | content = newContent }, Cmd.none)
Name name ->
({ model | name = name }, Cmd.none)
Password password ->
({ model | password = password }, Cmd.none)
PasswordAgain password ->
({ model | passwordAgain = password }, Cmd.none)
Roll ->
(model, Random.generate NewFace (Random.int 1 100))
NewFace newFace ->
({ model | diceRoller = { dieFace = newFace} }, Cmd.none)
SearchImages ->
(model, getSearchResult model.termInput)
NewSearchResult (Ok newResult) ->
( { model | termResult = newResult }, Cmd.none )
NewSearchResult (Err _) ->
(model, Cmd.none)
ChangeTermInput term ->
({ model | termInput = term}, Cmd.none)
我设法让它更精致了一点,但这无法编译(另请参阅 this Main.elm in the refactoring branch):
type DiceRollerMsg = Roll
| NewFace Int
type Msg = Change String
| Name String
| Password String
| PasswordAgain String
| MsgForDiceRoller DiceRollerMsg
| SearchImages
| NewSearchResult (Result Http.Error (List String))
| ChangeTermInput String
updateDiceRoller : DiceRollerMsg -> DiceRoller -> DiceRoller
updateDiceRoller msg model =
case msg of
Roll ->
model
NewFace newFace ->
{ model | dieFace = newFace}
updateDiceRollerCmd : Msg -> Cmd Msg
updateDiceRollerCmd msg =
case msg of
Roll ->
Random.generate NewFace (Random.int 1 100)
NewFace newFace ->
Cmd.none
updateCmd : Msg -> Model -> Cmd Msg
updateCmd msg model =
Cmd.batch
[ updateDiceRollerCmd msg
, getSearchResult model.termInput
]
updateModel : Msg -> Model -> Model
updateModel msg model =
case msg of
Change newContent ->
{ model | content = newContent }
Name name ->
{ model | name = name }
Password password ->
{ model | password = password }
PasswordAgain password ->
{ model | passwordAgain = password }
MsgForDiceRoller msg ->
{ model | diceRoller = updateDiceRoller msg model.diceRoller}
SearchImages ->
model
NewSearchResult (Ok newResult) ->
{ model | termResult = newResult }
NewSearchResult (Err _) ->
model
ChangeTermInput term ->
{ model | termInput = term}
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
(updateModel msg model, updateCmd msg model)
由于模式与 DiceRollerMsg 匹配,但它试图匹配 Msg。如果我只是将输入和 return 类型更改为 DiceRollerMsg,我会得到: Function updateDiceRollerCmd
is expecting the argument to be: DiceRollerMsg 但它是:Msg
我也不认为 updateCmd 中的 Cmd.batch 是这里最好的解决方案。
对于制作更好的 Elm 应用程序的任何意见,我都很感激,除了这些问题之外。
您的编译错误源于使用 Msg
作为输入和 updateDiceRollerCmd
的 return 值,而 case 语句使用 DiceRollerMsg
。您可以通过从 MsgForDiceRoller
.
updateDiceRollerCmd : Msg -> Cmd Msg
updateDiceRollerCmd msg =
case msg of
MsgForDiceRoller Roll ->
Random.generate NewFace (Random.int 1 100)
|> Cmd.map MsgForDiceRoller
_ ->
Cmd.none
您的视图中还有一个编译错误,您需要将 onClick Roll
更改为 onClick (MsgForDiceRoller Rool)