In this article, we’ll explore the top 10 mistakes in Vue.js and how to fix them with best practices and code examples.
1️⃣ Not Using key
in v-for Loops
❌ Mistake: Not Assigning a Unique Key in v-for
<li v-for="item in items">{{ item.name }}</li>
✔ Issue:
- Vue re-renders the entire list when data changes, reducing performance.
✅ Solution: Use a Unique key
in v-for
Loops
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
✔ Benefit: Optimizes list rendering by ensuring Vue tracks each item correctly.
2️⃣ Modifying Props Directly Inside Child Components
❌ Mistake: Changing Props in a Child Component
<script setup>
defineProps(['message']);
message = "New message"; // ❌ Mutating prop directly
</script>
✔ Issue:
- Props should be read-only, and modifying them breaks Vue’s reactivity system.
✅ Solution: Use computed
Properties or Emit Events
<script setup>
defineProps(['message']);
const updatedMessage = computed(() => message + " Updated!");
</script>
✔ Benefit: Preserves reactivity and ensures proper data flow.
3️⃣ Using v-if
and v-for
Together
❌ Mistake: Using v-if
and v-for
in the Same Element
<li v-for="item in items" v-if="item.show">{{ item.name }}</li>
✔ Issue:
- Vue evaluates
v-for
first, iterating over all elements before filtering, reducing efficiency.
✅ Solution: Use computed
to Filter the List Before Rendering
<template>
<li v-for="item in filteredItems" :key="item.id">{{ item.name }}</li>
</template>
<script setup>
const filteredItems = computed(() => items.filter(item => item.show));
</script>
✔ Benefit: Improves performance by filtering items before rendering.
4️⃣ Not Cleaning Up Event Listeners
❌ Mistake: Adding Event Listeners Without Removing Them
mounted() {
window.addEventListener("scroll", this.handleScroll);
}
✔ Issue:
- Memory leaks occur if listeners are not removed when the component is destroyed.
✅ Solution: Remove Event Listeners in onUnmounted
onMounted(() => window.addEventListener("scroll", handleScroll));
onUnmounted(() => window.removeEventListener("scroll", handleScroll));
✔ Benefit: Prevents memory leaks and ensures better performance.
5️⃣ Directly Modifying ref
Objects Instead of value
❌ Mistake: Changing ref
Object Instead of value
const counter = ref(0);
counter = 5; // ❌ Reassigning a ref object
✔ Issue:
- Vue does not detect changes if you reassign the entire
ref
object.
✅ Solution: Modify the .value
Property
const counter = ref(0);
counter.value = 5; // ✅ Updates correctly
✔ Benefit: Ensures reactivity is preserved.
6️⃣ Not Using Vue DevTools for Debugging
❌ Mistake: Debugging Without Vue DevTools
console.log(data); // ❌ Not efficient for debugging
✔ Issue:
- Harder to inspect reactivity issues and Vuex state changes.
✅ Solution: Use Vue DevTools
- Install Vue DevTools from here.
- Inspect components, Vuex state, and events in real-time.
✔ Benefit: Easier debugging and performance monitoring.
7️⃣ Using Global Variables Instead of Vuex/Pinia
❌ Mistake: Storing Global Data in window
or Local Storage
window.globalUser = { name: "John" }; // ❌ Not reactive
✔ Issue:
- No reactivity, and changes do not update the UI.
✅ Solution: Use Vuex or Pinia for State Management
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () => ({ name: "John" }),
});
✔ Benefit: Maintains reactive, centralized state management.
8️⃣ Not Lazy Loading Routes
❌ Mistake: Loading All Routes Eagerly
import Home from './views/Home.vue';
import About from './views/About.vue';
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About }
];
✔ Issue:
- Increases initial bundle size, slowing down page loads.
✅ Solution: Use Lazy Loading with defineAsyncComponent
const Home = defineAsyncComponent(() => import('./views/Home.vue'));
const About = defineAsyncComponent(() => import('./views/About.vue'));
✔ Benefit: Reduces initial load time and improves performance.
9️⃣ Using watch
Instead of computed
for Derived State
❌ Mistake: Using watch
to Compute Derived Data
const fullName = ref("");
watch(() => firstName.value + " " + lastName.value, (newVal) => {
fullName.value = newVal;
});
✔ Issue:
watch
is meant for side effects, not computing new values.
✅ Solution: Use computed
Instead
const fullName = computed(() => firstName.value + " " + lastName.value);
✔ Benefit: More efficient and automatically updates.
🔟 Not Securing API Requests
❌ Mistake: Sending API Requests Without Authorization
axios.get('/api/users'); // ❌ No authentication token
✔ Issue:
- Exposes sensitive data to unauthorized users.
✅ Solution: Attach Authorization Headers
axios.get('/api/users', {
headers: { Authorization: `Bearer ${token}` }
});
✔ Benefit: Ensures secure communication with APIs.
🎯 Conclusion
Vue.js is a powerful framework, but avoiding these common mistakes can help you build high-performance, secure, and maintainable applications.
✔ Use key
in v-for
loops for better rendering
✔ Avoid modifying props directly—use computed properties instead
✔ Unsubscribe from event listeners to prevent memory leaks
✔ Use Vuex/Pinia for state management
✔ Lazy load routes to optimize performance
✔ Secure API requests properly
By following these best practices, you’ll write better, more efficient Vue.js applications! 🚀
Comments
Post a Comment
Leave Comment