Vue.js 将事件传递给组件中的父级 [英] Vue.js passing events up to parents in components

查看:28
本文介绍了Vue.js 将事件传递给组件中的父级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的 Vue 应用:

<事件发射组件@clicked="methodOnRootInstance"></事件发射组件><事件发射组件父组件></事件发射组件父组件><div v-for="点击次数">{{ 点击 }}

这是它的 JS:

//孩子Vue.component('事件发射组件', {模板:'<div class="事件发射组件"@click="$emit(\'clicked\')">事件发射器</div>'});//父级Vue.component('事件发射组件父', {模板:'<div class="event-发射-component-parent">'+'自定义父级!'+'<事件发射组件></事件发射组件>'+//<-- 请注意子组件'</div>'});//创建一个根实例新的 Vue({el: '#example',数据: {点击:[]},方法 : {methodOnRootInstance :函数(){this.clicks.push('元素被点击');}}})

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

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

当您单击顶部子组件时,会在根元素上注册一次单击.完美.

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

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

我在这里做了一个精简的例子,但实际上有些组件有两到三层深.答案是(我认为是)在父组件中我会有以下内容:

Vue.component('事件-发射-组件-父', {模板:'<div class="event-发射-component-parent">'+'自定义父级!'+'<事件发射组件@clicked="passClicked"></事件发射组件>'+//<-- 请注意子组件'</div>','方法': {通过点击:函数(){this.$emit('点击')}}});

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

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

我知道我可以让它像这样工作,但是它看起来不太优雅.我查看了文档,并且有诸如 sync 之类的功能,尽管我认为这不是我需要的,但我正在努力寻找正确的方法.

额外的问题:vuex 可以帮助处理这样的事情吗?

解决方案

这是 vuex 旨在解决的问题类型,但是,在您考虑为应用添加额外的复杂层之前,您可能能够摆脱一个简单的全局事件总线,它只是一个空的 Vue 对象,用于向其发出事件,然后您的应用程序中的任何组件都可以监听它,绕过 <代码>父子链:

const bus = new Vue({});Vue.component('comp-1', {模板:`<div>Comp 1 <button @click="emitClick">Click</button></div>`,方法: {发射点击(){bus.$emit('comp-1-click');}}})Vue.component('comp-2', {模板:`<div><comp-1></comp-1></div>`,})新的 Vue({el: '#app',创建(){bus.$on('comp-1-click',() => {console.log('Comp 1 clicked');});}})

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

I have a Vue app like this:

<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>

And here is the JS for it:

// 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');
    }
  }
})

If you want to play with it it is also here:

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

When you click the top child component a click is registered on the root element. Perfect.

When the child component is nested inside a parent (the second component in the example), obviously I can't add a @clicked="methodOnRootInstance" as that method doesn't exist inside the component.

What is the best way to pass an event up through a number of nested components?

I've made a stripped back example here, but in reality some components are two or three levels deep. Is the answer (what I think it is) that inside the parent component I would have the following:

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')
    }
  }
});

And then in the html template add the same:

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

I know I can get it to work like this, however it doesn't seem very elegant. I've looked in the docs and there are functions such as sync although I don't think it's what I need, I'm struggling to find the correct approach.

Bonus question: can vuex help with stuff like this?

解决方案

This is the type of problem vuex is designed to solve, however, before you consider adding an extra layer of complexity to your app, you may be able to get away with a simple global event bus, which is simply an empty Vue object to emit events onto, which can then be listened for by any component in your app, bypassing the parent-child chain:

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');
    });
  }
})

Here's the JSFiddle: https://jsfiddle.net/oatLhzLp/

这篇关于Vue.js 将事件传递给组件中的父级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆