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

Posted

技术标签:

【中文标题】$emit an event from child to parent in vue.js, es6 语法【英文标题】:$emit an event from child to parent in vue.js, es6 syntax 【发布时间】:2017-03-11 02:00:41 【问题描述】:

我是 Vue.js 的新手,我使用 ES6 语法和 vue-class-component。我在尝试从孩子向其父母发出事件时遇到问题。

我遵循了默认 Vue.js 语法的逻辑,但我的父母似乎无法捕捉到孩子发出的事件。代码:

子组件

我在每个<li> 上附加了一个单击事件侦听器,它调用了一个发出事件的函数。事件监听器是在父级上定义的。

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

父组件

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

按照 vue.js 语法,我应该能够通过从元素发出事件来监听来自父级的子事件,但父级似乎没有捕获该事件。

我哪里错了?

【问题讨论】:

【参考方案1】:

您需要在要接收$emit 的视图模型上使用$emit,使用bus 或使用https://vuex.vuejs.org/。

直接发送给父级

最简单的方法,就是简单的$emit从子组件直接到父组件:

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

这是好的,但是如果您有一个长链组件,您需要将$emit 连接到链中的每个$parent

通过事件总线发射

您可以使用 Vue 非常简单地创建全局事件总线。您在主组件中创建一个 Vue 实例,然后应用程序中的所有其他组件可以emit 向它发送事件,并使用on 对这些事件做出反应。

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

也可以发送到$root,但不建议这样做。但是,如果您的 app 确实变得非常复杂,您可能需要考虑使用 Vues 自己的状态管理系统 vuex。

监听事件

您可以使用$on 在视图模型中侦听$emit 并侦听特定事件:

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

如果您使用的是总线,这也类似,但您只需引用总线:

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

您也可以使用v-on直接在您的html中使用它:

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

【讨论】:

谢谢克雷格!但是你怎么听父母的,我什么都听不懂…… 非常感谢克雷格!我也犯了一个错误,将 on-ChangeView 侦听器放在父级而不是实例本身上。所以解决我的问题的方法是: 在 ViewsContainer 中。再次感谢您的宝贵时间! 这里的ChangeView 是什么? 这是救生员。感谢您的信息。【参考方案2】:

Vue 中,您可以通过发出事件从子组件到父组件进行通信。 子组件 “发出”一个带有 $emit父组件 “监听”的事件 像这样:

子组件:

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

父组件:

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

您可以找到一个工作示例代码实现 here并在您自己的上下文中使用它。

【讨论】:

【参考方案3】:

除非我遗漏了某些东西(很可能),否则在像这样的简单示例中,您只需要在组件中侦听 emitted 事件即可。例如,在您的父元素中,您将拥有:

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

然后在您的子 (HorizontalNavigation) 组件中,您将 emit 'ChangeView' 事件:

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

根据您对@craig_h 的回答所做的评论,我自己在类似的代码中尝试了这个,这正是我所需要的。我不需要 emit 给父母,也不需要使用公共汽车或 vuex。

【讨论】:

花括号在我的代码中产生问题。 没有花括号并在组件的方法中实现 ChangeView 对我有用。【参考方案4】:

如果你最终在这里寻找 Vue 3 脚本设置

使用defineEmits 声明发射然后使用返回的函数发射是一种很好的可读性做法

子组件:

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

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

const handleClick = () => 
  emit('custom')

</script>

父组件:

<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 工作实现

【讨论】:

以上是关于$emit an event from child to parent in vue.js, es6 语法的主要内容,如果未能解决你的问题,请参考以下文章

$emit 不会触发子事件

vue2.x 父组件监听子组件事件并传回信息

$emit,$broadcast,$on用法,来源于http://www.tuicool.com/articles/qIBNve

理解.sync 的用法

How to Distinguish a Physical Disk Device from an Event Message

vue $emit child function to more parents