使用 "The Elm Architecture" 时如何存储子模块的状态

How to store states for sub-modules when using "The Elm Architecture"

我是 Function Programming(FP)Elm 的新手,所以用 FP 方式思考对我来说非常具有挑战性。

我正在开发一个与 Elm Tutorial.

示例非常相似的网络应用程序

为了简单起见,我们假设sub-module是一个计数器。 它将显示初始值 0 和两个按钮 increase/decrease 该值。

,---.     ,---.
| + | 123 | - |
`---'     `---'

我的应用程序的简化版本如下所示:

-------------------------------------
type alias Model =
    { contents : List Contents.Content
    , routing : Routing
    }

type Routing = List | Edit Int

view : Model -> Html
view model =
    case model.routing of 
        Edit id -> 
            let 
                maybe = List.head << (List.filter (\c -> c.id == id)) model.contents
            in 
                case maybe of 
                    Just content -> Contents.EditView content
                    Nothing -> div [] [ text "Error" ]

        List -> Contents.listView model.contents
------------------------------------
module Contents where 

type alias Content = { someKey : SomeType }

editView : Content -> Html
editView content =
    div []
        [ Counter.view WHERE_SHOULD_I_GOT_A_Counter.Model_FOR_THIS_CALL
        , someOtherViews content
        ]


listView : List Content -> Html
listView = 
    listViewImp
---------------------------
module Counter where

type alias Model = Int

view : Model -> Html
view model =
    div []
        [ button [] [ text "+" ]
        , text (toString model)
        , button [] [ text "-" ]
        ]

存在三级视图层次结构:

main view ----> edit view --> counter
            |-> list view

每次我从其他视图导航到 edit view 时,计数器值都应该为 0,然后应该只通过单击这两个按钮来修改它,直到我离开该页面。

问题是我应该从哪里得到一个 Counter.Model 传递给 Counter.view?

  1. 因为计数器是完全独立的,所以我不想让顶层视图知道它的存在,所以它不能从 view 函数发送。
  2. 如果我在 editView 函数中初始化一个 Counter.Model,每次调用 editView(可能由其他操作调用)都会将计数器重新初始化为 0

我希望我已经让自己明白了。

感谢阅读所有这些。

感谢大家的评论。

经过Elm Architecture tutorial again, I noticed that its code structure is somehow different from the one used in Elm Tutorial Gitbook之后。对于我的应用程序,最好使用 Elm 架构教程.

中描述的应用程序

有区别:

  • Elm Architecture 为所有子模块定义了 Model Action update viewinit
    • 实用模块不计入子模块这里
    • 有些Model Action... 可以省略的时候很简单
  • Elm Tutorial将某个概念的ModelsActions分开.elm 文件,并有几个 View 文件(Edit.elm List.elm 等)导入 Models操作数

当某个概念的不同视图仅取决于其 Model(或其变体,例如 List Model)时,我们可以采用 Elm 教程中使用的结构。原因是任何使用该概念的高级模块都会将 Model 初始化为 HighLevelModel 的一部分。但是当有一个视图不仅依赖于自身'Model',还需要另一个子模块时,我们就不能使用Elm Tutorial的结构了。在这种情况下,该视图可以被视为一个新模块(事实上,它是一个新模块),因此它应该有自己的 Model 类型并被高层模块导入。