Vue Component Lifecycle
Vue lifecycle hooks give you the opportunity to run code whenever Vue performs a certain action on your component. The hooks that Vue exposes for every component are:
beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestroydestroyed
The above list is in order. So Vue always calls beforeCreate before
created, and in turn Vue calls created before beforeMount.
To tell Vue to call a function on a given lifecycle hook, you simply add a method to your Vue instance or Vue component with the hook name as the property name:
// The below Vue instance has a `created` hook
const app = new Vue({
created: function() {
console.log('Called!');
},
template: `
<h1>Hello, World</h1>
`
});
// Prints "Called!"
app.$mount('#content');
Created
The created hook runs just after Vue creates an instance of your
Vue instance or component. In particular, created runs before mounted
and before the first render of the component. Since the component isn't
rendered yet, the $el property will be undefined.
You can use an async function as a created hook, but Vue won't wait
for the async function to finish before rendering the component.
// This Vue instance has an async created hook
const app = new Vue({
data: () => ({ answer: null }),
created: async function() {
await new Promise(resolve => setTimeout(resolve, 100));
this.answer = 42;
},
// Will first render "The answer is N/A", and then
// "The answer is 42" after 100 ms
template: `
<h1>The answer is {{answer == null ? 'N/A' : answer}}</h1>
`
});
Similarly, the beforeCreate hook runs just before Vue creates
the instance. One major difference between beforeCreate and create
is that beforeCreate runs before the Vue instance's data
function runs, so any reactive properties will be undefined in beforeCreate:
// This Vue instance has an beforeCreate hook
const app = new Vue({
data: () => ({ data: 'test' }),
beforeCreate: function() {
this.data; // undefined
},
template: `<div></div>`
});
Mounted
The mounted hook is the most commonly used hook. Vue runs mounted
after Vue "mounts" the component to the DOM. There are two major differences between mounted and created:
- When Vue calls
mounted, the$elproperty is defined and set to the DOM element the component is attached to. When Vue callscreated,$elis not set. - Vue's official server-side rendering package, vue-server-renderer, runs
createdhooks but notmountedhooks. This makes sense because, in server-side rendering, the Vue instance is never actually attached to a DOM element, vue-server-renderer simply outputs a string containing HTML.
The mounted hook is often used to send an HTTP request to load data for the component to display. For example, below is an example of using the mounted hook to send an HTTP request to load data about a user:
const url = 'https://jsonplaceholder.typicode.com/users/1';
const app = new Vue({
data: () => ({ user: null, error: null }),
// Display username if available, and error message if not
template: `
<div>
<div v-if="user != null">
{{user.name}}
</div>
<div v-if="error != null">
{{error.message}}
</div>
</div>
`,
mounted
});
async function mounted() {
try {
this.user = await axios.get(url).then(res => res.data);
this.error = null;
} catch (error) {
this.user = null;
this.error = error;
}
}
Whether you use created or mounted to fetch data over HTTP is open to debate.
The created hook runs first, which means you can parallelize fetching and
rendering. But, on the other hand, Vue's server side rendering doesn't wait for async created hooks to finish running, so you need to handle it yourself.
On the other hand, mounted runs after the component is mounted, which means
you can ensure a loading screen is shown before sending data to the server. Plus
it is easy to manually call a mounted hook for server-side rendering, so long
as the mounted hook doesn't rely on the DOM element $el. For example,
here's how you call the mounted() function from the previous example
on the server side:
await mounted.call(app);
const data = await renderToString(app);
// The HTML output contains the user data
assert.ok(data.includes('Leanne Graham'));
The beforeMount hook differs from the mounted hook in that the $el
property still isn't set. But, on the other hand, Vue also doesn't
run beforeMount when doing server-side rendering.
Updated
Vue runs the updated hook whenever it needs to re-render part of the
component after the component is mounted. Like mounted, Vue doesn't
run updated hooks when using server-side rendering.
window.numUpdated = 0;
const app = new Vue({
data: () => ({ count: 0 }),
updated: function() {
// Will print every time you click on the h1
console.log(++window.numUpdated);
},
template: '<h1 v-on:click="++count">Clicked {{count}}</h1>'
});
app.$mount('#content');
The updated and beforeUpdate hooks are typically useful only for
profiling and debugging. For example, you can plug in a print statement
to see when Vue needs to update, or track how long it took Vue to
update by storing the current time Date.now() in beforeUpdate and calculating the difference in updated.
You can't get a description of the necessary updates.
Destroyed
Vue calls the destroyed and beforeDestroy hooks when the Vue instance
is unmounted from the DOM. Vue calls beforeDestroy immediately before the
instance is unmounted, and destroyed immediately after. For example,
if you create a component for every element in an array elements using v-for,
Vue will call destroyed every time you remove an element from elements.
window.numDestroyed = 0;
Vue.component('test', {
destroyed: () => ++window.numDestroyed,
props: ['num'],
template: '<div class="test-element">{{num}}</div>'
});
const app = new Vue({
data: () => ({ elements: [1, 2, 3, 4] }),
destroyed: function() {
// Will print every time you click on the button, because
// Vue unmounts a `test` component every time you remove
// an element from `elements`.
console.log(++window.numDestroyed);
},
template: `
<div>
<test v-for="el in elements" :num="el"></test>
<button v-on:click="elements.splice(0, 1)">
Remove First
</button>
</div>
`
});
app.$mount('#content');
The destroyed hook is usually used for cleaning up global state, like calling clearInterval() if you started an interval in mounted.