我正在寻找有关在使用VueJS 2构建的实时消息/聊天应用中管理状态的一些指导。
该应用程序包含几个组件,如下图所示:
到目前为止,我已经实现了显示(假)对话。 App组件包含一个包含会话对象的数组。对于每个子组件,使用props传递相关数据。这很简单,就像一个魅力。
现在,我必须处理深深嵌套在树中的组件的动作/突变。例如,发送消息并将其附加到相应的消息数组中。
我认为它就像在AppConversationChatWindowInput组件中调度(全局)事件并在App组件中处理它一样简单。男孩,我错了。显然,this functionality was removed when Vue 2.0 was introduced支持Vuex。我不确定它为什么会被移除,因为在某些情况下,这可能是处理事件的完美合理方式。
我想有几种可能的解决方案:
将websocket连接传递给每个子组件。这在技术上可行。应用程序将连接到websocket服务器并使用props将此连接传递给其子组件。当用户发送消息时,它将由websocket服务器回显。 App组件可以侦听消息并将其附加到消息数组。
无论技术上的可行性如何,这对我来说都是一种糟糕且难以维护的结构。在我看来,App之外的任何组件都不应该知道websocket连接,更不用说它的具体实现了。
手动冒充链中每个组件中的事件。 这似乎是一个完全痛苦的维持。介绍了许多不必要的复杂性和失败点。
使用全局事件总线。 这是可能的,但为什么输入字段应该依赖于全局事件总线?我不喜欢不必要的依赖和耦合。它增加了复杂性并使测试更加困难。
使用全局数据存储(Vuex)。 见#3。另一个依赖和增加的复杂性另外,如果我愿意接受Vuex,我将如何检索组件中的数据?我是否使用组件传递它(就像我现在这样)或者树中的组件是否只是直接从商店中获取它?对我来说,感觉这个组件比它应该知道的要多得多。
有什么想法?在我的情况下处理状态的最佳方法是什么?
答案 0 :(得分:3)
&#34之间有点脱节;我想派遣一个全球性的活动"并且"我不想使用全球事件总线。"全局事件总线是您发送/广播全局事件的方式。正如您所指出的,在某些情况下,这是一个很好的解决方案。在你需要的时候设置并不难,所以没有充分的理由让它成为核心的Vue。
您可以将总线创建为instance property on Vue,以便每个组件都可以使用它:
Vue.prototype.$globalEventBus = new Vue();
您拥有vm.$dispatch(...)
的位置vm.$globalEventBus.$emit(...)
,接收组件可以设置vm.$globalEventBus.$on(...)
。
或者,您可以在顶层创建一个总线,并将其作为道具传递给孩子。这避免了全局变量,你不必担心冒泡。
最后,正如我在评论中指出的那样,原生事件会冒泡,你可以catch them at any component higher up the chain。您可以捕获发送消息的事件,甚至可以捕获roll your own个事件。