Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
329 views
in Technique[技术] by (71.8m points)

javascript - $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. 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. Code:

Child Component

I attached a click event listener on every <li>, which calls a function that emits an event. 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.

Where am I going wrong?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to $emit on the view model you want to receive your $emit, use a bus or use https://vuex.vuejs.org/.

Emitting to parent directly

The easiest way, is to simply $emit from the child directly to the parent component:

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.

Emiting via an Event Bus

You can use Vue to create a global event bus very simply. 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.

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. However, if your app does get quite complex you may want to consider using Vues own state management system, vuex, instead.

Listening for events

You can listen for the $emit in the viewmodel using $on and listening for the specific event:

    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:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...