javascript - 是否可以在 vue.js 中改变任意嵌套子组件的属性,而无需在整个层次结构中创建事件链?

标签 javascript typescript vue.js

在多个地方提到,改变属性是 vue.js 中的反模式。它警告用户不要这样做,即使在改变对象属性或使用像 this.$set 这样的函数将元素添加到作为属性给定的对象时也是如此。

鉴于此,让组件负责修改给定的某些数据的正确方法应该是什么? vue.js 建议的模式似乎正在发出事件,但请考虑这个虚构的示例:

// Main Component
<template>
   // content skipped for simplicity
   <some-component :someObject="something" />
</template>

// SomeComponent
// Passes this data to another component
<template>
    <another-component :someObject="someObject" />
</template>

// AnotherComponent
// Does things using someObjet

让我们想象一下,第三个组件 AnotherComponent 负责显示一些数据,这些数据是从使用最终使用这个组件的组件的主 UI 一直传递下来的。假设这个 AnotherComponent 甚至可以将此数据(或什至部分数据)传递给其他组件。

这是否意味着最终将修改此数据的组件(例如事物列表中的删除按钮)必须发出一个事件,然后该层次结构中的所有组件都必须监听这些事件并一直发射到原始组件,这是唯一一个实际允许改变对象的组件?

有更好的方法吗?

最佳答案

为了链接事件来执行父/深层子(或进行深层祖先/兄弟通信),对于简单的场景,you can use an event hub . (对于复杂的场景,请参阅 Vuex。)

您将创建一个全局变量:

var eventHub = new Vue(); // use a Vue instance as event hub

要发出您将在任何 组件中使用的事件:

eventHub.$emit('myevent', 'some value');

然后,您将在任何其他组件中收听该事件。该事件的 Action 可以是任何东西,包括更改数据的函数:

mounted() {
    eventHub.$on('myevent', (e) => {
        console.log('myevent received', e)
        this.someDataProperty = 'newValue' + e;
    });
}

演示:

var eventHub = new Vue(); // use a Vue instance as event hub

Vue.component('some-component', {
  template: "#some-component",
  props: ['someObject']
});
Vue.component('another-component', {
  template: "#another-component",
  props: ['someObject'],
  methods: {
    myMethod() {
      eventHub.$emit('myevent', ' <some event value> ' + this.someObject.toLowerCase());
    }
  }
})

new Vue({
  el: '#app',
  data: {
    something: 'initial value'
  },
  created() {
    eventHub.$on('myevent', (e) => {
      this.something = 'newValue-' + e;
    });
  }
})
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>

<template id="some-component">
    <div>
        some-component: {{ someObject }}
        <hr>
        <another-component :some-object="someObject" />
    </div>
</template>
<template id="another-component">
    <div>
    another-component: {{ someObject }}<br>
    <button @click="myMethod">Trigger event at 3rd level that will call some-component's method</button>
    </div>
</template>

<div id="app">
  Parent: {{ something }}
  <hr>
  <some-component :some-object="something" />
</div>

注意:如果创建专用实例作为事件中心在您的环境中比较复杂,您可以将 eventHub 替换为 this.$root (在您的组件内)并使用您自己的 Vue 实例作为中心。

关于javascript - 是否可以在 vue.js 中改变任意嵌套子组件的属性,而无需在整个层次结构中创建事件链?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49805132/

相关文章:

javascript - 使用 Google Maps API 合并多边形

javascript - jquery.matchHeight 的问题

javascript - 如何将字符串推送到 typescript 数组?

laravel - 如何索引没有公共(public)链接的谷歌动态页面?

vue.js - 使用槽范围问题 "Cannot read property ' column_name' of undefined 的元素 UI 表列

javascript - 画廊通过 jQuery 淡出和淡入

javascript - 如何对 JS 对象文字进行排序?

javascript - TypeScript 装饰器中的异步调用

javascript - 组件变量是否自动绑定(bind)到服务变量

vue.js - VueJS 在 props 中传递对象