我有一个包含各种组件的游戏UI,其中一些可以点击以突出显示(“活动”组件)。这是通过让Bool处于可以突出显示的每个组件的状态来完成的。但是,我想强制执行一次只能突出显示一个组件 - 因此,如果点击了某些内容,则当前突出显示的任何内容都必须更新为不突出显示。
这样做的一种方法是让共同的祖先向所有不同的孩子广播一些消息,并且每个组件都可以处理此消息并自行关闭 - 但这看起来非常复杂和浪费。可能有1000个组件,只有两个组件正在更改(一个用于突出显示,一个用于非高亮显示),那么我为什么要发送和处理1000条消息呢?
有更好的方法吗?
注意:这似乎与Elm 0.17: How to subscribe to sibling/nested component changes非常相似。我认为一个不同之处在于,在那个问题中存在少量相关组件,当一个组件发生变化时,另一个组件会发生变化。在我的情况下,整个模型中的不同位置有许多组件,当一个变化很少或其他任何一个都不会改变时。
答案 0 :(得分:5)
是的,可能有更好的方法。建议不要在应用程序的多个位置复制某些状态,因为这会导致同步问题并使调试更加困难。
相反,最好不要将突出显示的状态存储在组件中,而只存储在主模型中。然后组件的视图函数将采用另一个布尔“突出显示”参数。
要将突出显示的状态存储在主模型中,您可以为每个组件指定一个ID并将highlighted : Maybe ID
添加到模型中。
因此,您只需将点击消息从子节点传播到父节点,而不是从父节点传播到子节点。
答案 1 :(得分:1)
Elm运行时和虚拟DOM引擎将确保仅重新呈现更改的组件。因此,我不会过于担心向1,000个组件发送消息。
在你的情况下:
使用具有内部状态的组件时,您需要的是:
Bool
。
可以是组件model
。model
需要知道哪些组件是活动的。可能使用Maybe Int
,其中Int
是活动组件的ID。Msg
,其中应包含其ID,因此父级知道哪个组件现在处于活动状态。 (参见example here这可行的方法)update
函数在获取消息元素时更新其自身model
中的活动元素。父级更新1或2子组件以更改这些组件的活动标志。