Skip to content

9. project [vuejs-07]: event propagation in the component hierarchy

The project directory structure is as follows:

Image

9.1. The main script [main.js]

The main script [main.js] remains unchanged.

9.2. The main component [App]

The code for the [App] component is as follows:


<template>
  <div class="container">
    <b-card>
      <b-alert show variant="success" align="center">
        <h4>[vuejs-07]: Event propagation in the component hierarchy</h4>
      </b-alert>
      <Component1 />
    </b-card>
  </div>
</template>

<script>
  import Component1 from './components/Component1'
  export default {
    name: "app",
    components: {
      Component1
    }
  };
</script>

The [App] component uses a new [Component1] component (lines 7, 13, 17).

9.3. The [Component11] component

The code for the [Component11] component is as follows:


<template>
  <b-button @click="createEvent">Create an event</b-button>
</template>
<!-- script -->
<script>
  export default {
    name: "component11",
    // component methods
    methods: {
      // Handle the [click] event on the button
      createEvent() {
        // emit an event with data
        this.$emit("someEvent", { x: 2, y: 4 })
      }
    }
  };
</script>

Comments

  • lines 1–3: the [Component11] component contains only a button that can be clicked. When clicked, the [createEvent] method in lines 11–14 is executed;
  • line 13: each [View] instance has a [$emit] method that allows an event to be emitted:
    • the first parameter is the name of the emitted event;
    • the second parameter is the data to be associated with this event;
    • the emitted event travels up the hierarchy of components that contain the [Component11] component. It travels up the hierarchy until it finds a component capable of handling it. This process begins with the parent component of [Component11];

9.4. The [Component1] component

The code for the [Component1] component is as follows:


<template>
  <b-row>
    <!-- the component that triggers the event -->
    <b-col cols="2">
      <Component11 @someEvent="doSomething" />
    </b-col>
    <!-- message displayed by the event handler -->
    <b-col>
      <b-alert show
               variant="warning"
               v-if="showMsg">Event [someEvent] intercepted by [Component1]. Received value={{data}}</b-alert>
    </b-col>
  </b-row>
</template>

<script>
  import Component11 from "./Component11";
  export default {
    name: "component1",
    // components
    components: {
      Component11
    },
    // component state
    data() {
      return {
        data: "",
        showMsg: false
      };
    },
    // event handling methods
    methods: {
      doSomething(data) {
        // data is the object associated with the [someEvent] event
        this.data = data;
        // displays the alert
        this.showMsg = true;
      }
    }
  };
</script>

Visual rendering

Image

Image

Comments

  • line 5: [Component1] is the parent of [Component11] and can therefore “listen” (that’s the term) for events emitted by this component. We know that [Component11] can emit the [someEvent] event. The attribute [@someEvent="doSomething"] indicates that if the [someEvent] event emitted by [Component11] occurs, then the [doSomething] method on line 33 must be executed;
  • lines 9–11: a message displayed by the [doSomething] method. Its display is controlled by the Boolean [showMsg] on line 28. The alert displays the [data] attribute from line 27;
  • Line 33: The [doSomething] method, executed when the [someEvent] event occurs (line 5), receives the [data] associated with this event as a parameter. This parameter is assigned to the [data] attribute on line 27, which is displayed by line 11;
  • line 37: we set the [showMsg] attribute to [true] to display the alert from lines 9–11;

9.5. Running the project

Image