【问题标题】:Vue: how to fire an event on a sibling componentVue:如何在兄弟组件上触发事件
【发布时间】:2018-05-20 07:39:43
【问题描述】:

在 Vuejs 中,我有一个父组件(P)和两个子组件(C1 和 C2)。父组件具有与两个子组件共享的对象。

组件 C1 显示对象(在表格中),组件 C2 允许用户修改共享对象的属性。因为对象是作为对象共享的,所以我是直接在 C2 中更新它们的属性,并且在 C1 中显示更改。

问题在于 C1 负责保存更改(通过对服务器进行 ajax 调用)。如果用户直接在 C1 中修改属性,它会触发 change 事件,并且事件处理程序会进行调用。但是,如果属性在 C2 中更新,则不会在 C1 中触发更改事件,因此更改不会持久化。

那么,问题是,如何根据 C2 中的事件在 C1 中触发更改事件?我有一个事件总线(在根元素中)。我可以(也许)使用事件侦听器来获取元素(例如使用 jQuery)并触发事件,但显然这不是最优雅的方法。 Vue的方式是什么?

【问题讨论】:

  • 你应该在这种情况下使用 vuex。您的要求需要单一的事实来源。无论哪个组件触发它,只有 vuex 会存储/持久化更改!

标签: vue.js vue-component


【解决方案1】:

您的问题不太清楚。但是您可以使用eventBus,它会正常工作。

不过我的建议是使用vuex

您可以操作存储属性,并且每当属性更改时,更改将是反应性的并应用于所有组件。

因此,如果您有两个组件 c1 和 c2,并且在 store 中有一个属性 name: 'John Doe'

如果您在 c1 组件中更改名称,如:this.$store.state.name = 'Jane Doe',此更改也对组件 c2 生效。

当然不是那么简单。在 vuex 商店中,您应该有 state,getters,mutation,actions 并在您的组件上使用计算属性来使用通过 getter 获取商店属性。

【讨论】:

    【解决方案2】:

    希望我的理解正确:您在两个孩子之间共享一个对象,并且直接在任一子组件中操作该对象?

    这种模式本身就是问题所在。您不想在子组件内操作状态。保持反应性的干净方法是通过来自父组件的道具将对象绑定到两个子组件。孩子们不应该操纵 prop 对象的状态(如果你这样做,vue 实际上应该抛出一个警告),他们应该只发出一个他们想通过使用来更改对象的事件:

    this.$emit('input', newObject)
    

    现在只需在父级中侦听该事件并在那里操作对象,或者,为简单起见,您还可以使用 here 中描述的 v-model 模式。

    <c1 @input="myUpdateFunction" />
    

    或者使用 v-model 模式

    <c1 v-model="mySharedObject" />
    

    就是这样。如果您的其他组件也绑定了相同的对象作为道具,它将自动更新其模板。

    如果您想要一种更优雅的方式来共享整个应用程序的状态,我建议使用Vuex

    【讨论】:

    • 嗨菲利普,在本节的底部,vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow,它说当道具是一个对象时,孩子的变化会影响父母。你确定这不是一个好主意吗? (顺便说一句,我试用了 Vuex,但发现开销确实很大。)
    • 是的,我敢肯定,这也是它在文档中包含警告标志的原因。为此,您应该始终使用 v-model 方法。通过这种方法,您将正确使用 Vues 反应性模型,而不会产生任何副作用。实现 v-model 模式的子节点应该只操作状态的副本并通过事件将更改传达给父节点。这将允许以干净的方式将值传递给其他子组件,同时保持反应性。如果直接操作道具,vue 也会在控制台中显示警告(至少在使用 webpack 开发服务器时)。
    • @KimPrince 这是我快速组装的一个示例,说明如何使用 v-model 更新两个组件的状态:codesandbox.io/embed/oxy5o8985z
    • 谢谢菲利普,这太棒了。
    猜你喜欢
    • 1970-01-01
    • 2021-08-01
    • 2017-10-22
    • 2022-01-01
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    相关资源
    最近更新 更多