How to add Vue lifecycle listener dynamically

v-cloak
vue nexttick
vue methods
vue watch
vue mounted
v-once
vue watch immediate
vue mounted event listener

I have certain functions that I need to be able to call when a vue component is destroyed, but I don't necessarily know what they are before the event is created.

Is there a way to dynamically add a listener to the vue lifecycle events?

What I'm trying to achieve:

...methods: {
    logOnDestroy(txt) {
        this.$on('beforeDestroy', () => {
            console.log(txt)
        }
    }
}

But that is not currently being called. Is there a different way to programatically bind listeners to component lifecycle events at runtime?


You might ask, can it be simpler?

From Vue.js Component Hooks as Events, this is the syntax you are looking for

this.$once('hook:beforeDestroy', () => {

I'm not sure how exactly you intend to make it dynamic, but here is an adaption of your logOnDestroy() method in Vue CLI's default HelloWorld app,

Demo

Vue.component('helloworld', {
  template: '<h1>{{ msg }}</h1>',
  name: 'helloworld',
  props: { msg: String },
  mounted() {
    this.logOnDestroy('Goodbye HelloWorld')
  },
  methods: {
    logOnDestroy(txt) {
      this.$once('hook:beforeDestroy', () => {
        console.log(txt)
      })
    }    
  }
});

new Vue({
  el: '#app',
  data: {
    showHello: true
  },
  mounted() {
    setTimeout(() => {
      this.showHello = false
    }, 3000)
  }
});
Vue.config.productionTip = false
Vue.config.devtools = false
<script src="https://unpkg.com/vue"></script>
<div id="app">
  <img alt="Vue logo" src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/277px-Vue.js_Logo_2.svg.png" style="height: 50px;">
  <helloworld v-if="showHello" msg="Welcome to Your Vue.js App"/>
</div>

Dynamically Add Chart Event Listener using Vue, This article focuses on how you can dynamically add/remove event listener to the data plots in the chart using vue-fusioncharts component. A chart is shown below​  Adding and Removing Vue.js Watchers Dynamically Published on April 23, 2017 by Bo Andersen In this post, I want to show you how to add watchers dynamically, i.e. “outside” of the Vue instance.


Jan 2019 - A warning about the answer to this question - I found a subtle problem when using this code to add dynamic listeners.

this.$options.beforeDestroy.push(() => {
  console.log(txt)
});

It works ok when there is no static beforeDestroy defined. In this case the handlers array is a direct property of $options.

But if you define a static beforeDestroy hook on the component, the handlers array is property of $options.__proto__, which means multiple instances of the component inherit dynamic handlers of previous instances (effectively, the above code modifies the template used to create successive instances).

How much of a practical problem this is, I'm not sure. It looks bad because the handler array gets bigger as you navigate the app (e.g switching pages adds a new function each time).


A safer way of adding dynamic handlers is to use this injectHook code, which is used by Vue for hot module reload (you can find it in index.js of a running Vue app). Note, I am using Vue CLI 3.

function injectHook(options, name, hook) {
  var existing = options[name]
  options[name] = existing
    ? Array.isArray(existing) ? existing.concat(hook) : [existing, hook]
    : [hook]
}
...
injectHook(this.$options, 'beforeDestroy', myHandler)

What happens here is a new array is created on the instance which contains all the handlers from __proto__, plus the new one. The old array still exists (unmodified), and the new array is destroyed along with the instance, so there is no build-up of handlers in __proto__ handler array.

Vue.js Component Hooks as Events, Vue's lifecycle hooks emit custom events with the name of the hook itself, prefixed the same way you can create custom events dynamically. That’s all Vue lifecycle methods are and nothing more. Now you should be able to visualize the journey of a Vue instance whenever it is initialized and as well customize you own code using these various hooks or methods should the need arise.


An array of handlers for each life-cycle event is stored in the this.$options object. You can add a handler by pushing to the corresponding array (you'll need to create the array first if there are no handlers set already):

new Vue({
  el: '#app',
  created() {
    if (!this.$options.mounted) {
      this.$options.mounted = [];
    }
  
    this.$options.mounted.push(() => {
      console.log('mounted')
    });
    
    this.$options.mounted.push(() => {
      console.log('also mounted')
    });
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>

<div id="app">
  <div></div>
</div>

Handling Edge Cases, For example, imagine we add a new <google-map-region> component and This may be useful when you want to, for example, programmatically focus this input from a parent. component instance, when it's possible that only lifecycle hooks need access to it. You could resolve both issues with a programmatic listener: I would like to know how can I also dynamically bind listeners to the component - I have understand that I cannot send an object to v-on with multiple events. I was thinking about adding it programatically however haven't found any info about how it can be done for Vue custom events (kind for addEventListener equivalent for custom events)


One simple solution would be to simply track all dynamic handlers that you want to add inside the component:

Vue.component('foo', {
  template: '<div>foo component</div>',
  data() {
    return {
      beforeDestroyHandlers: []
    }
  },
  created() {
    this.beforeDestroyHandlers.push(() => {
      console.log('new handler called');
    });
  },
  beforeDestroy() {
    this.beforeDestroyHandlers.forEach(handler => handler());
  }
});

new Vue({
  el: '#app',
  data: {
    includeComponent: false
  }
});
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <button v-on:click="includeComponent = true">Add component</button>
  <button v-on:click="includeComponent = false">Destroy component</button>
  <foo v-if="includeComponent"></foo>
</div>

Components Basics, To pass a title to our blog post component, we can include it in the list of props this Above, you'll see that we can use v-bind to dynamically pass props. This is​  by Hassan Djirdeh An introduction to dynamic list rendering in Vue.js List rendering is one of the most commonly used practices in front-end web development. Dynamic list rendering is often used to present a series of similarly grouped information in a concise and friendly format to the user. In almost every web application we use, we can see lists of content in numerous areas of the app. In


Eric99's answer is instructive, but I feel there is something easier than fiddling with Vue's internals to do to achieve the same goal: use an event on the component. Easier to read, shorter to write.

Vue.component('foo', {
  methods {
    logOnDestroy (txt) {
      this.$on('beforeDestroy', () => {
        console.log(txt)
      })
    }
  },
  beforeDestroy () {
    this.$emit('beforeDestroy');
  }
});

You might ask: do I need to call this.$off() after I emit my event to prevent memory leaks? The answer is no, Vue does this for you automatically, so the above code is fine.

Vue.component, In 2.2.0+, this hook also captures errors in component lifecycle hooks. In 2.6.0+​, this hook also captures errors thrown inside v-on DOM listeners. This must be used to add new properties to reactive objects, as Vue cannot detect normal property Built-in Components - keep-alive; Dynamic Components - keep-alive​  Lifecycle hooks are an important part of any serious component. You often need to know when your component is created, added to the DOM, updated, or destroyed. Lifecycle hooks are a window into how the library you’re using works behind-the-scenes, and as such tend to invoke feelings of trepidation or unease for newcomers.


Vue dynamically add event listener, Vue dynamically add event listener. Sign in. The listener method does not bind the listener's lifecycle to the object that is the source of the event. The onload  Vue.js - The Progressive JavaScript Framework. Each Vue instance goes through a series of initialization steps when it’s created - for example, it needs to set up data observation, compile the template, mount the instance to the DOM, and update the DOM when data changes.


Vue.js Cheat Sheet, Properties of a Vue instance; Methods Data; Events; Lifecycle Methods v-show, similar to v-if , but adds the element to the DOM even if falsy. Just sets it listeners an object of v-on event listeners assigned to the component  Dynamically Add Chart Event Listener using Java FusionCharts Suite XT includes advanced features that let you add more context to your chart and make data visualization simpler. These features include chart updates, add events at runtime, and remove events at runtime.


8 secrets Vue Developers must know - DEV, listeners: An object containing parent-registered event listeners. Vue components lifecycle hooks don't run in the order you think they run With the power of dynamically register/unregister vuex modules we can improve the Here's my little tip, how to add multiple listeners to a functional component. 17.2.1 Handling Servlet Lifecycle Events. You can monitor and react to events in a servlet's lifecycle by defining listener objects whose methods get invoked when lifecycle events occur. To use these listener objects, you must define and specify the listener class.