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:
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
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$el
property is defined and set to the DOM element the component is attached to. When Vue callscreated
,$el
is not set. - Vue's official server-side rendering package, vue-server-renderer, runs
created
hooks but notmounted
hooks. 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
.