Emitting Custom Events in Vue

Tutorial 3 of 5

Introduction

In this tutorial, our main goal is to understand how to emit custom events in Vue.js. Custom events allow child components to communicate with their parent components, and this is a fundamental part of building reactive Vue applications.

By the end of this tutorial, you will learn:
- How to create and emit custom events in Vue.js
- How to listen for custom events in parent components
- Best practices when working with custom events

Prerequisites:
- Basic understanding of JavaScript
- Familiarity with Vue.js and its component system

Step-by-Step Guide

Vue.js allows components to communicate using a system of props and events. While props are used to pass data down from parent components to child components, events allow child components to send messages to their parent components.

In Vue.js, a child component can emit an event using the this.$emit method. The parent component can then listen for this event using the v-on directive or the shorthand @.

Example:

// Child Component
<template>
  <button @click="emitCustomEvent">Click me</button>
</template>

<script>
export default {
  methods: {
    emitCustomEvent() {
      this.$emit('my-custom-event', 'Hello, Parent!');
    }
  }
}
</script>

In this example, the child component emits a custom event called 'my-custom-event' when the button is clicked. The second argument to this.$emit is the payload of the event — in this case, the string 'Hello, Parent!'.

Code Examples

Now, let's see how the parent component can listen for this event.

// Parent Component
<template>
  <ChildComponent @my-custom-event="handleCustomEvent" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleCustomEvent(payload) {
      console.log(payload); // 'Hello, Parent!'
    }
  }
}
</script>

In this example, the parent component listens for the 'my-custom-event' using the v-on directive. When this event is received, the handleCustomEvent method is called with the event payload as its argument.

Summary

In this tutorial, we have learned how to emit custom events in Vue.js and how to listen for these events in parent components. This is a key part of building reactive Vue applications, as it allows child components to communicate with their parent components.

To further your learning, you might want to explore:
- How to pass multiple arguments to this.$emit
- How to emit and listen for events between sibling components
- How to use Vue's .sync modifier for two-way data binding

Practice Exercises

  1. Exercise: Create a child component that emits a 'change-color' event with a color value as the payload. The parent component should listen for this event and change its background color accordingly.

Solution: Here is a possible solution for this exercise.

// Child Component
<template>
  <button @click="changeColor">Change Color</button>
</template>

<script>
export default {
  data() {
    return {
      colors: ['red', 'green', 'blue'],
      currentColorIndex: 0
    };
  },
  methods: {
    changeColor() {
      this.$emit('change-color', this.colors[this.currentColorIndex]);
      this.currentColorIndex = (this.currentColorIndex + 1) % this.colors.length;
    }
  }
}
</script>
// Parent Component
<template>
  <div :style="{ backgroundColor: bgColor }">
    <ChildComponent @change-color="changeColor" />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      bgColor: 'white'
    };
  },
  methods: {
    changeColor(color) {
      this.bgColor = color;
    }
  }
}
</script>
  1. Exercise: Create a child component that emits a 'count-up' event every time a button is clicked. The parent component should listen for this event and increment a counter.

Solution: Here is a possible solution for this exercise.

// Child Component
<template>
  <button @click="$emit('count-up')">Count Up</button>
</template>
// Parent Component
<template>
  <div>
    <ChildComponent @count-up="counter++" />
    <p>Counter: {{ counter }}</p>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      counter: 0
    };
  }
}
</script>

In these exercises, remember to think about how the child and parent components are communicating. Understanding this will help you build complex Vue applications.