Skip to the content.

Vue.js Lifecycle Hooks - Complete Explanation πŸš€

In Vue.js, lifecycle hooks are special methods that let you execute code at different stages of a Vue instance’s life. Here’s an overview of all major lifecycle hooks:


1️⃣ Creation Phase (Instance is Created)

1. beforeCreate()

beforeCreate() {
    console.log("Before Create: ", this.message);  // Undefined
}

2. created()

created() {
    console.log("Created: ", this.message);  // Now accessible
}

2️⃣ Mounting Phase (DOM is Rendered)

3. beforeMount()

beforeMount() {
    console.log("Before Mount: ", this.message);
}

4. mounted() (Most Used)

mounted() {
    console.log("Mounted: ", this.message);
}

βœ… Example: Fetching data in mounted()

mounted() {
    fetch('https://api.example.com/data')
        .then(response => response.json())
        .then(data => {
            this.message = data.value;
        });
}

3️⃣ Updating Phase (Reactivity in Action)

5. beforeUpdate()

beforeUpdate() {
    console.log("Before Update: ", this.message);
}

6. updated()

updated() {
    console.log("Updated: ", this.message);
}

4️⃣ Destruction Phase (Instance is Destroyed)

7. beforeDestroy()

beforeDestroy() {
    console.log("Before Destroy: Cleaning up...");
}

8. destroyed()

destroyed() {
    console.log("Component Destroyed.");
}

🎯 Vue.js Lifecycle Hook Order (Execution Sequence)

1. beforeCreate()
2. created()
3. beforeMount()
4. mounted()
5. beforeUpdate()  (Only if data changes)
6. updated()       (Only if data changes)
7. beforeDestroy()
8. destroyed()

πŸ“Œ Full Example


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue Lifecycle Hooks</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>

<div id="app">
    <p>{{ message }}</p>
    <button @click="changeMessage">Change Message</button>
</div>

<script>
    new Vue({
        el: '#app',
        data() {
            return {
                message: "Hello Vue.js"
            };
        },
        beforeCreate() {
            console.log("1. Before Create: ", this.message);  // undefined
        },
        created() {
            console.log("2. Created: ", this.message);  // "Hello Vue.js"
        },
        beforeMount() {
            console.log("3. Before Mount: ", this.message);
        },
        mounted() {
            console.log("4. Mounted: ", this.message);
        },
        beforeUpdate() {
            console.log("5. Before Update: ", this.message);
        },
        updated() {
            console.log("6. Updated: ", this.message);
        },
        beforeDestroy() {
            console.log("7. Before Destroy: Cleaning up...");
        },
        destroyed() {
            console.log("8. Destroyed: Component removed.");
        },
        methods: {
            changeMessage() {
                this.message = this.message === "Hello Vue.js" ? "Vue Lifecycle" : "Hello Vue.js";
            }
        }
    });
</script>

</body>
</html>


🎯 Key Takeaways

🎯 Vue.js Lifecycle Hooks - Deep Explanation with Real-World Example & Diagrams

Vue.js lifecycle hooks allow you to execute code at different stages of a component’s life. Let's go step by step, using real-world examples and a diagram to visualize everything.


πŸ“Œ 1. Lifecycle Diagram (Execution Flow)

Here’s how Vue lifecycle hooks execute in order:

Creation Phase:
1. beforeCreate()   β†’  Data & methods not available yet
2. created()        β†’  Data & methods initialized

Mounting Phase:
3. beforeMount()    β†’  Virtual DOM compiled
4. mounted()        β†’  DOM elements inserted

Updating Phase:
5. beforeUpdate()   β†’  Called before data changes in the DOM
6. updated()        β†’  Called after DOM updates

Destroy Phase:
7. beforeDestroy()  β†’  Cleanup before removal
8. destroyed()      β†’  Component completely removed

πŸ”Ή Lifecycle Diagram

This diagram shows how lifecycle hooks interact with the component:

               Vue Instance
                 ⬇
    +-------------------------+
    |  beforeCreate()         |  πŸ”Ή Data & methods not available
    +-------------------------+
                 ⬇
    +-------------------------+
    |  created()              |  πŸ”Ή Data & methods available
    +-------------------------+
                 ⬇
    +-------------------------+
    |  beforeMount()          |  πŸ”Ή Template compiled
    +-------------------------+
                 ⬇
    +-------------------------+
    |  mounted()              |  πŸ”Ή DOM is ready
    +-------------------------+
                 ⬇
    +-------------------------+
    |  beforeUpdate()         |  πŸ”Ή Called before re-render
    +-------------------------+
                 ⬇
    +-------------------------+
    |  updated()              |  πŸ”Ή DOM updated
    +-------------------------+
                 ⬇
    +-------------------------+
    |  beforeDestroy()        |  πŸ”Ή Cleanup before removal
    +-------------------------+
                 ⬇
    +-------------------------+
    |  destroyed()            |  πŸ”Ή Component removed
    +-------------------------+

πŸ“Œ 2. Real-World Example

Imagine you’re building an e-commerce product page. You need to:
βœ” Fetch product details from an API when the page loads.
βœ” Show a loading spinner before the data loads.
βœ” Listen for cart updates when the user adds/removes products.
βœ” Remove event listeners when leaving the page.

Here’s how we apply lifecycle hooks:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue Lifecycle Example</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>

<div id="app">
    <h1>{{ product.name }}</h1>
    <p>{{ product.description }}</p>
    <p><strong>Price:</strong> ${{ product.price }}</p>
    <button @click="addToCart">Add to Cart</button>
    <p v-if="loading">Loading product...</p>
</div>

<script>
new Vue({
    el: "#app",
    data() {
        return {
            product: {},
            loading: true
        };
    },
    beforeCreate() {
        console.log("1️⃣ beforeCreate: Data not initialized");
    },
    created() {
        console.log("2️⃣ created: Fetching product...");
        setTimeout(() => {
            this.product = {
                name: "Smartphone",
                description: "A high-end smartphone with an amazing camera.",
                price: 999
            };
            this.loading = false;
            console.log("βœ… Product fetched");
        }, 2000);
    },
    beforeMount() {
        console.log("3️⃣ beforeMount: Template is compiled but not inserted into DOM.");
    },
    mounted() {
        console.log("4️⃣ mounted: Component is now in the DOM.");
        window.addEventListener("resize", this.handleResize);
    },
    beforeUpdate() {
        console.log("5️⃣ beforeUpdate: Data is changing...");
    },
    updated() {
        console.log("6️⃣ updated: DOM updated with new data.");
    },
    beforeDestroy() {
        console.log("7️⃣ beforeDestroy: Cleaning up event listeners...");
        window.removeEventListener("resize", this.handleResize);
    },
    destroyed() {
        console.log("8️⃣ destroyed: Component removed.");
    },
    methods: {
        addToCart() {
            console.log("πŸ“¦ Product added to cart!");
        },
        handleResize() {
            console.log("πŸ“ Window resized!");
        }
    }
});
</script>

</body>
</html>


πŸ“Œ 3. Understanding Execution with Logs

When you open the browser console, this is what you’ll see:

1️⃣ beforeCreate: Data not initialized
2️⃣ created: Fetching product...
3️⃣ beforeMount: Template is compiled but not inserted into DOM.
4️⃣ mounted: Component is now in the DOM.
βœ… Product fetched

When you add a product to the cart, the message appears:

πŸ“¦ Product added to cart!

When you close the page, Vue cleans up event listeners:

7️⃣ beforeDestroy: Cleaning up event listeners...
8️⃣ destroyed: Component removed.

πŸ“Œ 4. Summary of Lifecycle Hooks

Hook When it Runs Common Use Case
beforeCreate() Before Vue initializes data Logging, non-reactive setup
created() After Vue initializes data Fetch API, set up variables
beforeMount() Before inserting component in DOM Modify template before rendering
mounted() After inserting component in DOM Fetch API, event listeners
beforeUpdate() Before Vue updates the DOM Debugging before changes
updated() After Vue updates the DOM Work after reactivity updates
beforeDestroy() Before Vue removes component Cleanup timers, event listeners
destroyed() After Vue removes component Final cleanup, debugging

πŸ“Œ 5. When to Use Lifecycle Hooks

Scenario Best Lifecycle Hook
Fetch data from API created() or mounted()
Modify DOM directly mounted()
Listen for user events mounted()
Cleanup event listeners beforeDestroy()
Debug changes before update beforeUpdate()
Debug after reactivity change updated()

πŸ’‘ Conclusion


Awesome! Let’s reinforce your understanding with a quick quiz and then dive into a real-world Vue app example using lifecycle hooks. πŸš€


🎯 Quick Vue Lifecycle Quiz

Test yourself with these 5 multiple-choice questions!

Q1: Which lifecycle hook is best for fetching data from an API?

πŸ‘‰ Answer: created (B) βœ…
(Data is available, but the DOM isn’t yet mounted. API calls here ensure smooth rendering!)


Q2: Which hook runs when the component is fully inserted into the DOM?

πŸ‘‰ Answer: mounted (B) βœ…
(This is the best place to set up event listeners, access the DOM, or integrate with third-party libraries!)


Q3: When should you remove event listeners like window.addEventListener()?

πŸ‘‰ Answer: beforeDestroy (C) βœ…
(Ensures clean memory usage & prevents errors when switching components!)


Q4: What does beforeUpdate do?

πŸ‘‰ Answer: beforeUpdate (A) βœ…
(Great for debugging before Vue updates the DOM!)


Q5: If a Vue component is removed from the page, which hook runs last?

πŸ‘‰ Answer: destroyed (B) βœ…
(At this point, Vue has removed everything! You can perform any final cleanup here.)


πŸ”₯ Real-World Example: Vue Todo App with Lifecycle Hooks

Let’s build a Vue Todo App that: βœ” Fetches initial tasks from local storage.
βœ” Auto-saves tasks when updated.
βœ” Cleans up event listeners before closing.

Code:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue Todo App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>

<div id="app">
    <h1>Todo List</h1>
    <input v-model="newTask" @keyup.enter="addTask" placeholder="Add a task">
    <button @click="addTask">Add</button>
    
    <ul>
        <li v-for="(task, index) in tasks" :key="index">
            {{ task }}
            <button @click="removeTask(index)">❌</button>
        </li>
    </ul>
</div>

<script>
new Vue({
    el: "#app",
    data() {
        return {
            newTask: "",
            tasks: []
        };
    },
    beforeCreate() {
        console.log("1️⃣ beforeCreate: No tasks yet.");
    },
    created() {
        console.log("2️⃣ created: Loading tasks...");
        const savedTasks = localStorage.getItem("tasks");
        if (savedTasks) {
            this.tasks = JSON.parse(savedTasks);
        }
    },
    mounted() {
        console.log("3️⃣ mounted: Todo app is ready.");
        window.addEventListener("beforeunload", this.saveTasks);
    },
    beforeUpdate() {
        console.log("4️⃣ beforeUpdate: Task list is changing...");
    },
    updated() {
        console.log("5️⃣ updated: Task list updated!");
    },
    beforeDestroy() {
        console.log("6️⃣ beforeDestroy: Cleaning up...");
        window.removeEventListener("beforeunload", this.saveTasks);
    },
    destroyed() {
        console.log("7️⃣ destroyed: App removed.");
    },
    methods: {
        addTask() {
            if (this.newTask.trim()) {
                this.tasks.push(this.newTask.trim());
                this.newTask = "";
            }
        },
        removeTask(index) {
            this.tasks.splice(index, 1);
        },
        saveTasks() {
            localStorage.setItem("tasks", JSON.stringify(this.tasks));
            console.log("πŸ“ Tasks saved to local storage.");
        }
    }
});
</script>

</body>
</html>


πŸ“Œ Key Takeaways from This Todo App

1️⃣ Data Persistence – Saves tasks using localStorage.
2️⃣ Auto-Saving – Calls saveTasks() before closing the page.
3️⃣ Memory Cleanup – Removes event listeners in beforeDestroy().


Sure! A Student Planner App is a useful alternative to a Todo App. It helps students manage assignments, deadlines, class schedules, and reminders.

πŸ”₯ Let’s update our previous example with a Vue.js Student Planner App!


🎯 Vue Student Planner App

βœ… Features:

βœ” Add assignments with deadlines.
βœ” Sort assignments by due date.
βœ” Persist data using localStorage.
βœ” Show upcoming deadlines in red.
βœ” Remove completed assignments.


πŸ“Œ Code:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue Student Planner</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <style>
        body { font-family: Arial, sans-serif; text-align: center; margin: 20px; }
        .deadline-soon { color: red; font-weight: bold; }
    </style>
</head>
<body>

<div id="app">
    <h1>πŸ“š Student Planner</h1>

    <input v-model="newTask" placeholder="Enter assignment" @keyup.enter="addTask">
    <input type="date" v-model="newDeadline">
    <button @click="addTask">Add</button>

    <ul>
        <li v-for="(task, index) in sortedTasks" :key="index">
            {{ task.name }} - 
            <span :class="{ 'deadline-soon': isDeadlineSoon(task.deadline) }">
                Due: {{ task.deadline }}
            </span>
            <button @click="removeTask(index)">❌</button>
        </li>
    </ul>
</div>

<script>
new Vue({
    el: "#app",
    data() {
        return {
            newTask: "",
            newDeadline: "",
            tasks: []
        };
    },
    beforeCreate() {
        console.log("1️⃣ beforeCreate: No assignments loaded yet.");
    },
    created() {
        console.log("2️⃣ created: Loading assignments...");
        const savedTasks = localStorage.getItem("tasks");
        if (savedTasks) {
            this.tasks = JSON.parse(savedTasks);
        }
    },
    mounted() {
        console.log("3️⃣ mounted: Planner is ready.");
        window.addEventListener("beforeunload", this.saveTasks);
    },
    beforeDestroy() {
        console.log("6️⃣ beforeDestroy: Cleaning up...");
        window.removeEventListener("beforeunload", this.saveTasks);
    },
    methods: {
        addTask() {
            if (this.newTask.trim() && this.newDeadline) {
                this.tasks.push({ name: this.newTask.trim(), deadline: this.newDeadline });
                this.newTask = "";
                this.newDeadline = "";
            }
        },
        removeTask(index) {
            this.tasks.splice(index, 1);
        },
        saveTasks() {
            localStorage.setItem("tasks", JSON.stringify(this.tasks));
            console.log("πŸ“ Assignments saved.");
        },
        isDeadlineSoon(deadline) {
            const today = new Date();
            const dueDate = new Date(deadline);
            const diffTime = dueDate - today;
            const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
            return diffDays <= 2; // Highlight tasks due in 2 days
        }
    },
    computed: {
        sortedTasks() {
            return this.tasks.sort((a, b) => new Date(a.deadline) - new Date(b.deadline));
        }
    }
});
</script>

</body>
</html>


πŸ”₯ Key Features of This App

πŸ“… Assignments – Add assignments with due dates.
⚠ Deadline Alerts – Upcoming deadlines (within 2 days) turn red.
πŸ“Š Sorting – Tasks auto-sort by due date.
πŸ’Ύ Persistence – Tasks saved in localStorage.
πŸ›  Cleanup – Event listeners removed in beforeDestroy().


πŸš€ What’s Next?

Create :