简化单击时更改布尔值的按钮

Simplifying button that when clicked changes boolean value

我创建了一个包含布尔值的按钮,当您单击它时,它会更改该值和按钮内的文本。下面的代码有效,但我觉得我做得有点矫枉过正。我怎样才能把这个按钮写得尽可能简单,但仍然遵循 ELM 架构?

module BtnPin where

import Html exposing ( Html )
import Html.Events as E
import StartApp.Simple as StartApp

-- MAIN

main =
  StartApp.start { model = emptyModel, view = view, update = update }

-- MODEL

type alias Model =
    {pinned : Bool}

init : Model
init = Model False

emptyModel : Model
emptyModel =
    { pinned = False
    }

pin : Model -> Model
pin model =
    if model.pinned then
        Model False
    else
        Model True

viewPin : Signal.Address Action -> Model -> Html
viewPin address model =
    if model.pinned == True then
        Html.button
            [ E.onClick address Pin ]
            [ Html.text <| "Unpin" ]
    else
        Html.button
            [ E.onClick address Pin ]
            [ Html.text <| "Pin" ]

-- UPDATE

type Action = Pin 

update : Action -> Model -> Model
update action model =
  pin model 

-- VIEW

view : Signal.Address Action -> Model -> Html
view address model =
    Html.div []
    [ viewPin address model ]

你越明确,越接近 Elm 架构,对于了解该模式的人来说,阅读起来就越容易。它也很容易扩展。但是您当然可以简化您不希望更改的组件。

请记住,对于您问题中的代码,您唯一需要的文档是一句话描述,因为代码是 Elm 架构,所有内容都有类型注释并且非常简单。压缩代码时,您可能需要更多文档。

一个简化的按钮:

module BtnPin where

import Html exposing ( Html )
import Html.Events as E
import StartApp.Simple as StartApp

main =
  StartApp.start { model = False, view = view, update = always not }

-- VIEW

view : Signal.Address () -> Bool -> Html
view address model =
  Html.div [] [ viewPin address model ]

viewPin : Signal.Address () -> Bool -> Html
viewPin address model =
  let
    text = if model then "Unpin" else "Pin"
  in
    Html.button
      [ E.onClick address () ]
      [ Html.text text ]

这可能有点极端,所以你可以通过定义一个update函数、一个Model类型和一个Action类型来妥协。但是你离起点很近了...