简体   繁体   English

$emit an event from child to parent in vue.js, es6 语法

[英]$emit an event from child to parent in vue.js, es6 syntax

I'm pretty new to Vue.js, and I use ES6 syntax with vue-class-component .我对 Vue.js 很陌生,我使用 ES6 语法和vue-class-component I'm having a problem while trying to emit an event from a child to its parent.我在尝试从孩子向其父母发出事件时遇到问题。

I followed the logic of the default Vue.js syntax but can't seem to have my parent catch an event emitted by the the child.我遵循了默认 Vue.js 语法的逻辑,但似乎无法让我的父母捕捉到孩子发出的事件。 Code:代码:

Child Component子组件

I attached a click event listener on every <li> , which calls a function that emits an event.我在每个<li>上附加了一个单击事件侦听器,它调用一个发出事件的函数。 The event listener is defined on the parent.事件侦听器是在父级上定义的。

 export default class HorizontalNavigation {

  handleClick (e) {
    e.preventDefault();
    // console.log(e.target.dataset.section);
    this.$emit('ChangeView', e.target.dataset.section);
  }

  render (h) {
    return (
      <div class={ style.horizontalNavigation } >
        <div class='sections-wrapper'>
          <div class={ style.sections }>
            <ol>
              <li><a on-click={ this.handleClick } href='#1' data-section='1' class='selected'>We are</a></li>
              <li><a on-click={ this.handleClick } href='#2' data-section='2'>Services</a></li>
              <li><a on-click={ this.handleClick } href='#3' data-section='3'>Cases</a></li>
              <li><a on-click={ this.handleClick } href='#4' data-section='4'>Studio</a></li>
              <li><a on-click={ this.handleClick } href='#5' data-section='5'>Career</a></li>
              <li><a on-click={ this.handleClick } href='#6' data-section='6'>Contact</a></li>
            </ol>

            <span class='filling-line' aria-hidden='true'></span>
          </div>
        </div>
      </div>
    );
  }
}

Parent Component父组件

export default class ViewsContainer {

  ChangeView (data) {
    console.log(data);
  }

  render (h) {
      return (
        <div class={ style.restrictOverflow } >
          <HorizontalNavigation />
          <main class={ style.viewsContainer } on-ChangeView={ this.ChangeView     } >
            <SingleView dataSection='weare' id='1' class='selected' />
            <SingleView dataSection='services' id='2' />
            <SingleView dataSection='cases' id='3' />
            <SingleView dataSection='studio' id='4' />
            <SingleView dataSection='career' id='5' />
            <SingleView dataSection='contact' id='6' />
          </main>
        </div>
      );
    }
}

Following the vue.js syntax, I should be able to listen to the child's event from the parent, by emitting the event from the element, but the parent doesn't seem to catch the event.按照 vue.js 语法,我应该能够通过从元素发出事件来从父级监听子级的事件,但父级似乎没有捕捉到该事件。

Where am I going wrong?我哪里错了?

You need to $emit on the view model you want to receive your $emit , use a bus or use https://vuex.vuejs.org/ .您需要在要接收 $ $emit的视图模型上$emit ,使用bus或使用https://vuex.vuejs.org/

Emitting to parent directly直接发送给父母

The easiest way, is to simply $emit from the child directly to the parent component:最简单的方法是直接从子组件$emit到父组件:

this.$parent.$emit('ChangeView', e.target.dataset.section);

This is OK , but if you have a long chain of components you need to $emit to each $parent in the chain.没关系,但如果你有一个长链组件,你需要$emit到链中的每个$parent

Emiting via an Event Bus通过事件总线发射

You can use Vue to create a global event bus very simply.您可以使用 Vue 非常简单地创建全局事件总线。 You create an instance of Vue in your main component, then all other components in your application can emit events to it, and use on to react to those events.您在主组件中创建一个 Vue 实例,然后应用程序中的所有其他组件都可以向它emit事件,并使用on对这些事件做出反应。

var bus = new Vue({});
var vm = new Vue({
  methods: {
    changeView() {
      bus.$emit('ChangeView', e.target.dataset.section);
    }
  });

It is also possible to emit to $root but this isn't recommended.也可以发送到$root ,但不建议这样做。 However, if your app does get quite complex you may want to consider using Vues own state management system, vuex , instead.但是,如果您的app确实变得非常复杂,您可能需要考虑使用 Vues 自己的状态管理系统vuex

Listening for events监听事件

You can listen for the $emit in the viewmodel using $on and listening for the specific event:您可以使用$on监听 viewmodel 中的$emit并监听特定事件:

    var vm = new Vue({
      created() {
         this.$on('ChangeView', section => {
            console.log(section);
          });
      }
    );

This would also be similar is you were using the bus, but you would just reference the bus instead:如果您使用的是总线,这也类似,但您只需引用总线:

bus.$on('ChangeView', ...);

And you may also use it directly in your html using v-on :您也可以使用v-on在您的 html 中直接使用它:

<div v-on:ChangeView="doSomething"></div>

In Vue , you can communicate from children up to parent components by emitting events .Vue中,您可以通过发出事件从子组件到父组件进行通信。 The child compoment "emits" an event with $emit & the parent component "listens" for it like so:组件“发出”带有$emit的事件,父组件“监听”它,如下所示:

Child Component:子组件:

<template>
  <div>
    <button @click="this.handleClick">Click me!</button>
  </div>
</template>

<script>
export default {
  name: "BaseButton",
  methods: {
    handleClick: function() {
      this.$emit("clickFromChildComponent");
    }
  }
};
</script>

<style scoped>

</style>

Parent Component:父组件:

<template>
  <div class="home">
    <h1>Passing a event from child up to parent!</h1>
    <BaseButton @clickFromChildComponent="handleClickInParent"/>
  </div>
</template>

<script>
import BaseButton from "./BaseButton";

export default {
  components: {
    BaseButton
  },
  name: "Home",
  methods: {
    handleClickInParent: function() {
      alert('Event accessed from parent!');
    }
  }
};
</script>

<style scoped>

</style>

You can find a working sample code implementation here & use it in your own context.您可以在此处找到一个工作示例代码实现并在您自己的上下文中使用它。

Unless I'm missing something (very likely), in a simple example like this, you just need to listen for the emit ted event in your component.除非我遗漏了某些东西(很可能),否则在像这样的简单示例中,您只需要在组件中侦听emit的 ted 事件。 For example, in your parent element, you would have:例如,在您的父元素中,您将拥有:

<HorizontalNavigation v-on:ChangeView={this.ChangeView} />

Then in your child ( HorizontalNavigation ) component, you would emit the 'ChangeView' event:然后在您的子 ( HorizontalNavigation ​​ntalNavigation ) 组件中,您将emit “ChangeView”事件:

this.$emit('ChangeView', e.target.dataset.section);

I tried this in similar code myself, based on a comment you made on @craig_h's answer, and it was what I needed.根据您对@craig_h 的回答所做的评论,我自己在类似的代码中尝试了这个,这正是我所需要的。 I didn't need to emit to parent, or use a bus, or vuex.我不需要向父母emit信号,也不需要使用总线或 vuex。

If you end up here looking for Vue 3 script setup如果您最终在这里寻找 Vue 3 脚本设置

It's good practice for readibility to declare emits with defineEmits and then use the returned function for emitting使用defineEmits声明发射,然后使用返回的函数发射是一种很好的可读性做法

Child component :子组件:

<template>
  <div>
    <button @click="handleClick">Increment</button>
  </div>
</template>

<script setup>
const emit = defineEmits(['custom'])

const handleClick = () => {
  emit('custom')
}
</script>

Parent component :父组件:

<template>
  <h1>{{ counter }}</h1>
  <Button @custom="handleCustom"/>
</template>

<script setup>
import { ref } from 'vue'
import Button from './components/Button.vue'

const counter = ref(0)

const handleCustom = () => {
  counter.value++
}
</script>

Here is the working implementation 这是工作实现

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM