javascript - 如何在 Elm 中创建有状态、模块化、独立的 Web 组件?

标签 javascript elm

假设您要创建一个包含 3 个按钮的 UI。当您单击其中一个时,其他的将被释放。在 JavaScript 中,你可以这样写:

var elements = ["Foo","Bar","Tot"].map(function(name){
  var element = document.getElementById(name);
  element.onclick = function(){
    elements.map(function(element){
      element.className = 'button';
    });
    element.className = 'button selected';
  };
  return element;
});
.button {
  border: 1px solid black;
  cursor: pointer;
  margin: 4px;
  padding: 4px;
}
.selected {
  background-color: #DDDDDD;
}
<div>
  <span id='Foo' class='button'>Foo</span>
  <span id='Bar' class='button'>Bar</span>
  <span id='Tot' class='button'>Tot</span>
</div>
  

这是有状态的,但不是模块化的,独立的也不是纯粹的。事实上,状态(一个三进制位)甚至不明显是很糟糕的。你不能将它注入(inject)另一个模型,你想要多少次。

到目前为止,此处提供的大多数答案都是有状态的,但不是模块化的。问题是使用该策略,您不能将一个组件放入另一个而父级不了解子级模型。理想情况下,这将被抽象掉——父节点不需要在其自己的模型中提及子节点的模型,也不需要手动将状态从父节点连接到节点。如果我想创建上面应用程序的列表,我不想将每个子节点的状态存储在父节点上。

如何在 Elm 中创建有状态的、模块化的、独立的网络组件?

最佳答案

Elm 可以满足这些要求中的每一个,使您的组件有状态、模块化、独立且纯净。这是 Elm 中使用 StartApp.Simple 的示例(请原谅内联样式):

import StartApp.Simple exposing (start)
import Html exposing (Html, div, span, text)
import Html.Attributes exposing (id, class, style)
import Html.Events exposing (onClick)

type alias Model =
  { elements : List String
  , selected : Maybe String
  }

init : Model
init =
  { elements = [ "Foo", "Bar", "Tot" ]
  , selected = Nothing
  }

type Action
  = Select String

update : Action -> Model -> Model
update action model =
  case action of
    Select s ->
      { model | selected = Just s }

view : Signal.Address Action -> Model -> Html
view address model =
  let 
    btn txt =
      span
        [ id txt
        , buttonStyle txt
        , onClick address <| Select txt
        ] [ text txt ]

    buttonStyle txt =
      style (
        [ ("border", "1px solid black")
        , ("cursor", "pointer")
        , ("margin", "4px")
        , ("solid", "4px")
        ] ++ (styleWhenSelected txt))

    styleWhenSelected txt =
      case model.selected of
        Nothing -> []
        Just s ->
          if s == txt then
            [ ("background-color", "#DDDDDD") ]
          else
            []
  in
    div [] <| List.map btn model.elements


main =
  start
    { model = init
    , update = update
    , view = view
    }

您有一个明确定义的静态类型模型、可以针对该模型执行的明确且数量有限的操作,以及一个类型安全的 html 渲染引擎。

看看 Elm Architecture Tutorial获取更多信息。

关于javascript - 如何在 Elm 中创建有状态、模块化、独立的 Web 组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34018333/

相关文章:

php - JavaScript + PHP + 动态文本字段 + Jquery

javascript - IE8 仅在鼠标悬停在 <body> 之外时显示背景图像

javascript - Knockout attr href 输出问题

elm - 按模块/命名空间引用内置类型

javascript - 如何在 Elm 中捕获服务器事件

javascript - jquery提示保存数据onbeforeunload

javascript - 使用链接更改 div

javascript - 原生 JavaScript 类型是如何用 Elm 编写的?

elm - 如何批量处理多个http调用?

dom - 使用 Elm.Browser.Dom 按类名获取元素