Combining Vue.js with various events and dynamic components

I am facing an issue with my Vue.js application. I have a simple root component App that contains two different components, Room and Machine. Both of these components include another component called Datatable, which is the same for both of them. To switch between Room and Machine, I am using dynamic components mechanism. However, each time I change the component, the event is being sent multiple times. According to my understanding, the old component should be destroyed and a new one created when switching, so I'm confused as to why this behavior is occurring.

When I switch between components, the console shows multiple events being emitted: https://i.sstatic.net/sIhDB.png

Here are the components in my application:

App.vue:

<template>
    <div id="app">
        <select style="padding: 10px" v-model="currentModule" @change="changeComponent">
            <option value="Room">Room</option>
            <option value="Machine">Machine</option>
        </select>
        <component :is="currentModule"></component>
    </div>
</template>

<script>
    import Room from './Room.vue';
    import Machine from './Machine.vue';


    export default {
        name: 'app',
        components: {
            Room,
            Machine
        },
        data () {
            return {
                currentModule: 'Room'
            }
        },
        methods: {
            changeComponent: function() {
                Event.$emit('moduleHasChanged', this.currentModule)
            }
        },
    }
</script>

Machine.vue:

<template>
    <div>
        Machine template

        <datatable></datatable>
    </div>
</template>
<script>
    import Datatable from './Datatable.vue';

    export default {
        components: {
            Datatable
        }
    }
</script>

Room.vue:

<template>
    <div>
        Room template

        <datatable></datatable>
    </div>
</template>
<script>
    import Datatable from './Datatable.vue';

    export default {
        components: {
            Datatable
        }
    }
</script>

Datatable.vue

<template>
    <div>
        Datatable
    </div>
</template>

<script>
    export default {
        created() {
            Event.$on('moduleHasChanged', (currentModule) => {
                console.log(currentModule);
            })
        }
    }
</script>

Answer №1

The reason for this issue is the continuous addition of event listeners when the Datatable component is created without removing them afterwards. Normally, Vue takes care of handling this automatically, but in this case with an event bus, manual removal is required.

To resolve this, simply include a beforeDestroy handler to remove the event listener.

console.clear()
const Event = new Vue()

const Datatable = {
  template: `
    <div>
      Datatable
    </div>
  `,
  methods: {
    moduleChanged(currentModule) {
      console.log(currentModule);
    }
  },
  created() {
    Event.$on('moduleHasChanged', this.moduleChanged)
  },
  beforeDestroy() {
    Event.$off('moduleHasChanged', this.moduleChanged)
  }
}

const Room = {
  template: `
    <div>
      Room template
      <datatable></datatable>
    </div>
  `,
  components: {
    Datatable
  }
}

const Machine = {
  template: `
    <div>
      Machine template
      <datatable></datatable>
    </div>
  `,
  components: {
    Datatable
  }
}

const App = {
  name: 'app',
  template: `
    <div id="app">
        <select style="padding: 10px" v-model="currentModule" @change="changeComponent">
            <option value="Room">Room</option>
            <option value="Machine">Machine</option>
        </select>
        <component :is="currentModule"></component>
    </div>
  `,
  components: {
    Room,
    Machine
  },
  data() {
    return {
      currentModule: 'Room'
    }
  },
  methods: {
    changeComponent: function() {
      Event.$emit('moduleHasChanged', this.currentModule)
    }
  },
}


new Vue({
  el: "#app",
  render: h => h(App)
})
<script src="https://unpkg.com/@vue/dist/vue.js"></script>
<div id="app">

</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issues with Angular-UI-router resolve functionality not functioning as expected

I have encountered a problem in my Angular-ui-router where the use of resolve is causing my site to send out multiple get requests per second without loading the view. My stack consists of the full MEAN-stack. The views are generated using inline template ...

problem when testing html file using javascript jasmine

Is it necessary to have a .js suffix when testing an html file with the D3.js javascript library using jasmine, or can HTML files also be tested with jasmine? ...

Issue encountered while attempting to import three.js in static context

Trying to statically import three.js for a test website. I'm a bit rusty with html/js so something seems off here. Following static import from Code below (all in one html file): <script type="module"> // Find the latest v ...

"Utilize Vue.js to easily share a webpage on Facebook with a simple

Can anyone help me out with a dilemma I'm facing? I am currently in the process of developing a blog website using Vue Router, which results in dynamic routes like https:/myblog.com/post/a-post-title. One important feature I need to include is sharing ...

Could the comments within a NodeJS script be causing memory problems?

I specialize in creating NodeJS libraries, and my coding practice includes adding JSDoc comments for documentation purposes. Here is an example of how my code usually looks: /** * Sum * Calculates the sum of two numbers. * * @name Sum * @function * ...

What steps should I take to diagnose the cause of the 503 errors plaguing my node.js server?

At the moment, I am delving into the world of node.js as a hobby. A while back, my server was up and running smoothly, producing simple 'hello world' outputs. However, after some recent tinkering, it seems like something went wrong with my node.j ...

The Material-ui paper component fails to display on the screen

The material-ui paper component is implemented on my homepage and functioning correctly. However, when navigating to another page and returning to the homepage, the paper component disappears, leaving only text rendered. Can you help me identify the issue? ...

Incorporating a value into vue.js will increase the existing number by the specified amount

Encountering a strange issue while setting up a pagination system. Attempting to increment the value for the next page by 1, but instead of increasing, it appears that the value is being appended. this.page = 1 <a v-if="this.total_pages > thi ...

Trigger the rowContextMenu in Tabulator Table by clicking a Button

Is there a way to add a button at the end of a table that, when clicked, opens a rowContextMenu below the button? Additionally, can the rowContextMenu pop up when right-clicking anywhere on the row? I have attempted some solutions without success. Here is ...

Using Tinymce 4.1.9 with raw ajax instead of JQuery: A step-by-step guide

I am currently working with Tinymice 4.1.9 for textarea validation in a raw ajax environment as I have limited knowledge of jquery. The issue I'm facing is that when Tinymce 4.1.9 is added to the textarea, upon validation, I receive an empty string un ...

Differences in Function Scope: A Comparison of ECMAScript 6 and ECMAScript 5

What are the advantages of ES6 compared to ES5 when it comes to block scope functions? Although the blocks may look similar in both cases, what impact does it have performance-wise and which approach is more efficient? ES6 Block { function fo ...

The Angular @HostListener beforeunload Event is a powerful way to handle

I've implemented the following code snippet in my main app.component.ts file within my Angular 17 project: @HostListener("window:beforeunload", ["$event"]) onTabClose($event: BeforeUnloadEvent) { $event.preventDefault(); ...

Responsive Bar Chart using jQuery Mobile and ChartJS that appears on the screen only after resizing

I have been experimenting with adding a responsive bar chart using Chart.js in one of my JQM projects. Here is what I have accomplished so far: http://jsfiddle.net/mauriciorcruz/1pajh3zb/3/ The Chart needs to be displayed on Page Two and it should be res ...

The persistent issue of window.history.pushstate repeatedly pushing the identical value

I need some assistance with my Vue application. I am trying to update the URL when a user clicks on an element: const updateURL = (id: string) => { window.history.pushState({}, '', `email/${id}`); }; The issue I'm facing is th ...

The Vue framework has been designated as an external dependency within the single-spa configuration, but an issue has arisen

Currently utilizing Vue with single-spa, I have embarked on a mission to minimize the bundle size. In pursuit of this goal, my initial approach involved configuring Vue as an external dependency in the webpack.config.js file for each Micro Front-end: exte ...

Include the root prefix in angular.json

Within my angular.json file, I am utilizing the following code snippet: "root": "admin/", "sourceRoot": "src", "prefix": "app", "architect": { "build": { " ...

Mastering the art of jQuery scrolling: A step-by-step guide

Is there a way to utilize jQuery for scrolling purposes? For example, transforming this: <ul class="nav navbar-nav navbar-right"> <li class="active"><a href="#home">Home <span class="sr-only">(current)</span></a> ...

Checking variable length time with JavaScript Regular Expression

My specific requirement is to validate a string ranging from 1 to 4 characters in length (where H stands for hour and M represents minutes): If the string has 1 character, it should be in the format of H (a digit between 0-9). A 2-character string should ...

What is the proper way to internally submit a form?

I am interested in the possibility of internally submitting form data. For instance, let's say I want to register an account for a website. Typically, this would involve filling out a form on the site itself. However, I am considering creating my own ...

Tips on how to efficiently wrap content within a column layout, and to seamlessly shrink it if necessary

I recently encountered an issue where I am attempting to create a three-column layout with each column filled with a dynamic number of divs (boxes) ranging from 5 to 15, each with its own height based on its content. These divs are expected to: 1) Be dis ...