榆树中是否有一种模式可以避免编写大量消息,而只是为了更新模型子元素上的各个字段?
此刻,我将获得以下代码,每个更改的输入信息,然后是每个字段的更新逻辑。我想做的是有一条消息,如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
}
答案 0 :(得分:4)
对于这个问题,我采取了两种截然不同的方法。使您获得最大控制权(同时仍有助于消除冗长性)的一种方法是使用广义的Update
将逻辑从View
移至Msg
。类似于:UpdateForm (String -> Model)
或UpdateForm (String -> FormModel)
。
另一种方法是完全不将输入状态存储在模型中。不利的一面是不允许您执行诸如初始化输入或轻松清除输入之类的操作。但是,这是一种快速而又肮脏的获取基本表格的方法。在这种方法中,您利用了具有name
属性的输入元素成为父form
元素 1 的属性的事实。您可以将解码器附加到表单的onSubmit
并通过Decode.at ["ab", "value"]
获取值。
1 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-name