1

我从一个非常简单的应用程序开始使用 om 和 ClojureScript。

我的全局应用状态如下所示:

(def app-state (atom {:animals [ {:name "dog" :img "pic01.jpg"}
                                 {:name "cat" :img "pic02.jpg"}
                                 {:name "mouse" :img "pic03.jpg"}
                                 {:name "camel" :img "pic04.jpg"}]}))

向量“animals”中每个哈希映射的 name 属性由我称为“menu”的 om 组件呈现为 HTML 列表结构(例如 LI 标记)。每个条目都由另一个称为“条目”的组件呈现。(例如作为 UL 元素)。每当用户将鼠标悬停在列表条目之一时,条目的外观就会发生变化(可能背景会发生变化)。我在入口组件中捕获这些当前状态,我通过 om/IInitState 对其进行初始化。

到目前为止,这有效。现在我想添加另一个组件,称为“显示”。每当用户单击列表中的条目时,它应该能够在全局状态下显示与动物名称相关联的图像。我问自己解决这个问题的最佳方法是什么。

我看到两种可能性:

在“显示”组件中保持本地状态,该状态由“条目”组件的 onClick 事件更新。在这里,我的问题是:如何从另一个组件更新组件的状态?

或者在全局状态中引入另一个属性,可能叫做:“active_section”,由entry组件中的onClick事件更新,由“display”组件读取。但这有必要吗?

4

2 回答 2

2

Not sure I understand your requirements 100%, but will throw in my 2 cents worth.

In general, I would avoid a design which involves one component somehow updating local state in another component. This would create tight coupling between the components, which is probably not something you really want. Far better off to design/develop your components so that they have as little, if any, knowledge about other components.

The best approach with react based apps is to keep your state in the global state atom. In this case, I would have one component (the menu component?) set a :visible or :current property value in your global state which indicates the current animal. Your other component would render the animal based on the entry with this property set to true.

The other advantage of doing it this way is that should you decide to add additional components which need to operate on whichever 'animal' is current, it can also use that information.

Keeping all state change which may trigger DOM rendering in one place can also make debugging easier. Also, check out om-next (there is a quick start tutorial) as it has a new approach for setting/geetting state which promises to make things a lot simpler than the old 'cursor' approach.

于 2015-12-29T02:46:51.590 回答
1

我使用两种不同的方法。第一个是让组件“广播”它的状态作为消息。例如,我有一个“广播”它是“当前日期”的日历组件。当有人点击不同的日期时,它会广播该新日期。任何组件都可以侦听该消息并根据需要进行自我更新。

我的第二种方法是让组件向“另一个”组件广播消息。它通过广播其他组件正在侦听的“类型”消息来做到这一点。例如,我有一个想要编辑客户的组件。它将想要编辑的“客户”广播到“客户编辑组件”。“客户编辑组件”决定它是否可以显示客户并处理编辑。如果它决定保存更改,则广播“保存”消息。“保存”消息列表处理请求并广播“保存”的结果。显示客户信息的组件处理“更新的”客户消息并显示更改。

唯一的耦合是在消息总线和消息之间。所有这些都是使用 core.async 实现的。

您应该预先决定的问题是是否拥有多个总线(通道)。另一个问题是组件需要将未定向到它们的消息短路。

我有一个特殊的组件可以侦听所有消息以进行调试。

我会小心地将所有全局数据直接绑定到组件。我更愿意将全局数据视为数据库,而不是组件的内部数据。

于 2015-12-29T18:50:38.010 回答