Vue.js将事件传递给组件中的父项

时间:2017-06-06 11:44:59

标签: vue.js vuejs2

我有一个像这样的Vue应用程序:

<div id="example">

  <event-emitting-component @clicked="methodOnRootInstance"></event-emitting-component>

  <event-emitting-component-parent></event-emitting-component-parent>

  <div v-for="click in clicks">
    {{ click }}
  </div>

</div>

以下是它的JS:

// Child
Vue.component('event-emitting-component', {
  template: '<div class="event-emitting-component" @click="$emit(\'clicked\')">Event emitter</div>'
});
// Parent
Vue.component('event-emitting-component-parent', {
  template: '<div class="event-emitting-component-parent">' +
  'A custom parent!'+
  '<event-emitting-component></event-emitting-component>' + // <-- Please note child component
  '</div>'
});
// create a root instance
new Vue({
  el: '#example',
  data: {
    clicks : []
  },
  methods : {
    methodOnRootInstance : function(){
      this.clicks.push('Element clicked');
    }
  }
})

如果你想玩它,它也在这里:

https://codepen.io/EightArmsHQ/pen/QgbwPG?editors=1010

单击顶部子组件时,将在根元素上注册单击。完美。

当子组件嵌套在父组件(示例中的第二个组件)中时,显然我无法添加@clicked="methodOnRootInstance",因为组件内部不存在该方法。

通过多个嵌套组件传递事件的最佳方法是什么?

我在这里做了一个剥离的例子,但实际上有些组件是两层或三层深。答案(我认为是什么)在父组件内部我会有以下内容:

Vue.component('event-emitting-component-parent', {
  template: '<div class="event-emitting-component-parent">' +
  'A custom parent!'+
  '<event-emitting-component @clicked="passClicked"></event-emitting-component>' + // <-- Please note child component
  '</div>',
  'methods': {
    passClicked : function(){
      this.$emit('clicked')
    }
  }
});

然后在html模板中添加相同的内容:

<event-emitting-component-parent @clicked="methodOnRootInstance"></event-emitting-component-parent>

我知道我可以让它像这样工作,但它看起来并不优雅。我已查看了文档,并且有sync之类的功能,虽然我不认为这是我需要的,但我很难找到正确的方法。< / p>

奖金问题:vuex可以帮助这样的事情吗?

1 个答案:

答案 0 :(得分:1)

这是问题vuex旨在解决的问题,但是,在考虑为应用添加额外的复杂层之前,您可以使用简单的全局事件总线,这是只需要一个空的Vue对象来发送事件,然后可以通过应用中的任何组件监听,绕过parent-child链:

const bus = new Vue({});

Vue.component('comp-1', {
  template: `<div>Comp 1 <button @click="emitClick">Click</button></div>`,
  methods: {
     emitClick(){
       bus.$emit('comp-1-click');
     }
  }
})


Vue.component('comp-2', {
  template: `<div><comp-1></comp-1></div>`,
})

new Vue({
  el: '#app',
  created(){
    bus.$on('comp-1-click',() => {
      console.log('Comp 1 clicked');
    });
  }
})

这里是JSFiddle:https://jsfiddle.net/oatLhzLp/