榆树中是否有一种模式可以避免编写大量消息只是为了更新模型子元素上的各个字段?
目前,我的代码如下所示,每个输入都会更改一条消息,然后每个字段都有一堆更新逻辑。我想做的是有一条像 AChanged 这样的消息,它处理对 A 的任何属性的所有更改。通过更新生成消息的函数中的记录或传递字段名称,然后使用它直接执行像在 Javascript 中一样更新记录。
module Main exposing (Model)
import Browser exposing (Document, UrlRequest)
import Browser.Navigation as Nav exposing (Key)
import Html exposing (div, input)
import Html.Events exposing (onInput)
import Url exposing (Url)
type alias A =
{ a : String
, b : String
, c : String
, d : String
}
type alias B =
{ e : String
, f : String
, g : String
, h : String
}
type alias Model =
{ key : Nav.Key
, url : Url.Url
, a : A
, b : B
}
type Msg
= UrlChanged Url.Url
| LinkClicked Browser.UrlRequest
| AaChanged String
| AbChanged String
| AcChanged String
| AdChanged String
| BeChanged String
| BfChanged String
| BgChanged String
| BhChanged String
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flag url key =
( Model key url (A "" "" "" "") (B "" "" "" ""), Cmd.none )
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
view : Model -> Document msg
view model =
{ title = "Mister Mandarin"
, body =
div
[ input [ onInput AaChanged ] []
, input [ onInput AbChanged ] []
, input [ onInput AcChanged ] []
, input [ onInput AdChanged ] []
, input [ onInput BeChanged ] []
, input [ onInput BfChanged ] []
, input [ onInput BgChanged ] []
, input [ onInput BhChanged ] []
]
[]
}
update : Msg -> Model -> ( Model, Cmd msg )
update msg model =
case msg of
LinkClicked urlRequest ->
case urlRequest of
Browser.Internal url ->
( model, Nav.pushUrl model.key (Url.toString url) )
Browser.External href ->
( model, Nav.load href )
UrlChanged url ->
( { model | url = url }
, Cmd.none
)
AaChanged value ->
let
a =
model.a
newA =
{ a | a = value }
in
( { model | a = newA }, Cmd.none )
AbChanged value ->
let
a =
model.a
newA =
{ a | b = value }
in
( { model | a = newA }, Cmd.none )
AcChanged value ->
let
a =
model.a
newA =
{ a | c = value }
in
( { model | a = newA }, Cmd.none )
AdChanged value ->
let
a =
model.a
newA =
{ a | d = value }
in
( { model | a = newA }, Cmd.none )
BeChanged value ->
let
b =
model.b
newB =
{ b | e = value }
in
( { model | b = newB }, Cmd.none )
BfChanged value ->
let
b =
model.b
newB =
{ b | f = value }
in
( { model | b = newB }, Cmd.none )
BgChanged value ->
let
b =
model.b
newB =
{ b | g = value }
in
( { model | b = newB }, Cmd.none )
BhChanged value ->
let
b =
model.b
newB =
{ b | h = value }
in
( { model | b = newB }, Cmd.none )
main : Program () Model Msg
main =
Browser.application
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
, onUrlChange = UrlChanged
, onUrlRequest = LinkClicked
}