Introduction to Vue.js
Vue.js (commonly referred to as Vue) is a progressive JavaScript framework for building user interfaces. Unlike monolithic frameworks, Vue is designed to be incrementally adoptable, allowing you to use as much or as little of the framework as you need.
Vue was created by Evan You in 2014 after working with AngularJS at Google. He aimed to extract the parts he liked about Angular while creating a lightweight framework that was more approachable and flexible.
Key Characteristics of Vue.js
- Approachable: Can be learned in a short time, even for developers new to frontend frameworks
- Progressive: Can be adopted incrementally in existing projects or used to build full single-page applications
- Versatile: Adaptable ecosystem that scales between a library and a full-featured framework
- Performant: Small runtime (~33KB min+gzip) with efficient rendering and updating
- Maintainable: Focused on component-based development with clear separation of concerns
Real-world analogy: If frameworks were vehicles, Vue would be like a modular electric vehicle – you can start with a basic model and add features as needed. It's easy to drive, energy-efficient, and you can customize it extensively without having to replace the entire vehicle.
Vue.js Version History
Understanding Vue's evolution helps to contextualize its architecture:
- Vue 1.x (2014): Initial release focused on simple reactivity and directives
- Vue 2.x (2016): Added Virtual DOM, component system improvements, and better performance
- Vue 3.x (2020): Complete rewrite with Composition API, TypeScript support, and better performance
We'll be focusing on Vue 3 in this course, as it represents the current direction and best practices for Vue development.
Major Architectural Changes in Vue 3
- Proxy-based reactivity system (replacing Object.defineProperty)
- Composition API (alongside Options API)
- Fragment support (multiple root elements in components)
- Tree-shaking friendly design
- Smaller bundle size
- Improved TypeScript support
Core Architecture
Vue's architecture consists of several key parts that work together to create a reactive, component-based system:
Reactivity System
The reactivity system is at the heart of Vue. It automatically tracks dependencies between data and the DOM, updating the UI when data changes.
In Vue 3, the reactivity system is built using JavaScript Proxies, which intercept property access and modifications:
// Vue 3 Reactivity System (simplified)
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
track(target, key); // Track that this property was accessed
return target[key];
},
set(target, key, value) {
target[key] = value;
trigger(target, key); // Trigger updates for components that depend on this property
return true;
}
});
}
// Usage
const state = reactive({ count: 0 });
state.count++; // Automatically triggers UI updates
Real-world analogy: The reactivity system works like a smart home. When you change the thermostat setting (data), sensors (dependency tracking) detect this change and automatically adjust the heating or cooling systems (DOM updates) without you having to manually control each component.
Template Compilation
Vue templates are HTML-based templates with special directives and syntax. The template compiler converts these templates into render functions that create Virtual DOM nodes:
// Vue Template
<div>
<p>{{ message }}</p>
<button v-if="showButton" @click="increment">
Count: {{ count }}
</button>
</div>
// Compiled to (simplified)
function render() {
return h('div', [
h('p', state.message),
state.showButton
? h('button', { onClick: increment }, `Count: ${state.count}`)
: null
]);
}
This compilation can happen at build time (for better performance) or at runtime (for flexibility).
Virtual DOM
Vue uses a Virtual DOM to efficiently update the actual DOM. The Virtual DOM is a lightweight JavaScript representation of the real DOM:
- Render functions create Virtual DOM nodes
- When data changes, a new Virtual DOM tree is created
- Vue compares the new and old Virtual DOM trees (diffing)
- It applies only the necessary changes to the real DOM (patching)
Real-world analogy: Think of the Virtual DOM like an architect's blueprint. Instead of rebuilding an entire house (the DOM) when you want to make changes, you modify the blueprint (Virtual DOM) first, then the construction team (Vue's patching algorithm) reviews the differences and only replaces or modifies the necessary parts of the structure.
Component Architecture
Vue is built around the concept of components – reusable, self-contained pieces of code that encapsulate markup, styles, and logic.
Single-File Components (SFCs)
Vue's most distinctive feature is Single-File Components (SFCs) with the .vue file extension. These files contain template, script, and style blocks in one file:
<!-- Counter.vue -->
<template>
<div class="counter">
<h2>{{ title }}</h2>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
export default {
name: 'Counter',
props: {
title: {
type: String,
default: 'Counter'
}
},
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++;
}
}
}
</script>
<style scoped>
.counter {
border: 1px solid #ccc;
padding: 1rem;
margin: 1rem 0;
}
</style>
SFCs provide several benefits:
- Complete encapsulation of component logic, template, and styles
- Easier to understand, maintain, and reuse
- CSS scoping to avoid style leakage
- Better IDE/tooling support
- Preprocessor support for HTML, CSS, and JavaScript
Real-world analogy: SFCs are like prefabricated rooms for a house. Each room comes complete with walls (structure), electrical systems (logic), and decoration (styles), ready to be connected to other rooms to form a complete house (application).
Component Lifecycle
Vue components have a lifecycle with hooks that allow you to run code at specific stages:
export default {
// Creation hooks
beforeCreate() {
console.log('Component is being initialized');
},
created() {
console.log('Component instance created');
// Good place for API calls and data initialization
},
// Mounting hooks
beforeMount() {
console.log('Template compiled, about to mount');
},
mounted() {
console.log('Component mounted to DOM');
// Good place for DOM manipulations and integrations
},
// Updating hooks
beforeUpdate() {
console.log('Data changed, about to update DOM');
},
updated() {
console.log('DOM updated after data change');
},
// Unmounting hooks
beforeUnmount() {
console.log('About to unmount component');
// Clean up resources, event listeners, etc.
},
unmounted() {
console.log('Component unmounted from DOM');
}
}
Options API vs. Composition API
Vue 3 offers two ways to define component logic: the Options API (traditional) and the Composition API (new in Vue 3).
Options API
The Options API organizes code into object options like data, methods, and computed:
<script>
export default {
name: 'UserProfile',
// Data properties
data() {
return {
user: null,
loading: false,
error: null
}
},
// Computed properties
computed: {
fullName() {
return this.user ? `${this.user.firstName} ${this.user.lastName}` : ''
}
},
// Methods
methods: {
async fetchUser(id) {
this.loading = true;
try {
const response = await fetch(`/api/users/${id}`);
this.user = await response.json();
} catch (err) {
this.error = err.message;
} finally {
this.loading = false;
}
}
},
// Lifecycle hooks
created() {
this.fetchUser(this.$route.params.id);
}
}
</script>
Composition API
The Composition API lets you organize code by logical concerns rather than option types:
<script setup>
import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
// State
const user = ref(null);
const loading = ref(false);
const error = ref(null);
// Computed properties
const fullName = computed(() => {
return user.value ? `${user.value.firstName} ${user.value.lastName}` : '';
});
// Methods
async function fetchUser(id) {
loading.value = true;
try {
const response = await fetch(`/api/users/${id}`);
user.value = await response.json();
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
}
// Lifecycle
const route = useRoute();
onMounted(() => {
fetchUser(route.params.id);
});
</script>
Key benefits of the Composition API:
- Better organization for complex components by grouping related code
- Enhanced TypeScript support
- More flexible code reuse through "composables" (similar to React hooks)
- Better tree shaking for smaller bundles
Real-world analogy: The Options API is like organizing your kitchen by types of items (all utensils in one drawer, all ingredients in one cabinet). The Composition API is like organizing by recipes or meal types, keeping all related items together regardless of their type.
Vue.js Ecosystem
Vue's ecosystem includes several official libraries and tools that extend its capabilities:
Core Libraries
- Vue Router: Official routing library for creating single-page applications
- Vuex/Pinia: State management libraries (Pinia is newer and recommended for Vue 3)
- Vue Test Utils: Testing utilities for Vue components
Development Tools
- Vue CLI: Command-line tool for scaffolding projects (traditional)
- Vite: Next-generation build tool with extremely fast development server
- Vue DevTools: Browser extension for debugging Vue applications
Frameworks Built on Vue
- Nuxt.js: Full-featured framework for server-side rendering, static site generation, and more
- Quasar: UI framework and build system for cross-platform applications
- Gridsome: Static site generator for content-focused websites
Setting Up a Vue Project
There are several ways to start a Vue project, from simple to more complex:
Using CDN for Simple Projects
<!DOCTYPE html>
<html>
<head>
<title>Vue 3 CDN Example</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
<button @click="count++">Count: {{ count }}</button>
</div>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const message = ref('Hello Vue 3!');
const count = ref(0);
return {
message,
count
};
}
}).mount('#app');
</script>
</body>
</html>
Using Vite (Recommended for Modern Development)
# Create a new Vue 3 project
npm create vite@latest my-vue-app -- --template vue
# Navigate to project folder
cd my-vue-app
# Install dependencies
npm install
# Start the development server
npm run dev
The project structure will look like:
my-vue-app/
├── public/ # Static assets that will be served as-is
├── src/
│ ├── assets/ # Dynamic assets that will be processed by the build system
│ ├── components/ # Vue components
│ │ └── HelloWorld.vue
│ ├── App.vue # Root component
│ └── main.js # Application entry point
├── index.html # HTML entry point
├── package.json # Dependencies and scripts
├── vite.config.js # Vite configuration
└── README.md
Entry Point: main.js
import { createApp } from 'vue'
import App from './App.vue'
// Create a Vue application instance
const app = createApp(App)
// Mount the app to a DOM element
app.mount('#app')
This simple structure can be extended with plugins and other features:
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { createPinia } from 'pinia'
import App from './App.vue'
import routes from './routes'
// Create the app instance
const app = createApp(App)
// Create the router
const router = createRouter({
history: createWebHistory(),
routes
})
// Create the store
const pinia = createPinia()
// Add plugins to the app
app.use(router)
app.use(pinia)
// Mount the app
app.mount('#app')
How Vue Compares to Other Frameworks
Vue vs React
- Template System: Vue uses HTML-based templates, while React uses JSX
- State Management: Vue has official solutions (Vuex/Pinia), React has many third-party options
- Learning Curve: Vue is often considered easier to learn, especially for beginners
- Component Structure: Vue uses SFCs, React typically uses JS/JSX files
- Flexibility: Both are flexible, but Vue has more built-in features
Vue vs Angular
- Size and Complexity: Vue is lighter and less opinionated than Angular
- Corporate Backing: Angular is backed by Google, Vue is community-driven
- TypeScript Integration: Angular is built with TypeScript, Vue supports it but doesn't require it
- Learning Curve: Vue is generally easier to learn and use than Angular
- Architecture: Angular is a complete platform, Vue is a progressive framework
Real-world usage tends to vary by project needs and team preferences. Vue is particularly strong in scenarios where:
- Progressive enhancement of existing applications is needed
- Development teams include designers or developers with HTML/CSS backgrounds
- Project complexity is moderate and clean, maintainable code is a priority
- Fast iteration and development speed are important
Practice Activity
Set Up Your First Vue 3 Project
- Use Vite to create a new Vue 3 project
- Examine the project structure and understand each file's purpose
- Modify the App.vue file to create a simple counter application
- Implement both Options API and Composition API versions
For the Counter App:
- Display a counter with increment and decrement buttons
- Add a reset button that sets the counter back to zero
- Add a title that can be customized
- Display whether the current count is even or odd
Start with this template for the Options API version:
<template>
<div class="counter-app">
<h1>{{ title }}</h1>
<p class="count">Count: {{ count }}</p>
<p class="info">The count is currently {{ evenOrOdd }}</p>
<div class="buttons">
<!-- Add your buttons here -->
</div>
</div>
</template>
<script>
export default {
name: 'CounterApp',
props: {
title: {
type: String,
default: 'Vue Counter'
}
},
data() {
return {
count: 0
}
},
computed: {
// Add your computed property for evenOrOdd
},
methods: {
// Add your methods for increment, decrement, and reset
}
}
</script>
<style scoped>
.counter-app {
max-width: 400px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
text-align: center;
}
.count {
font-size: 2rem;
font-weight: bold;
}
.buttons {
display: flex;
justify-content: center;
gap: 10px;
margin-top: 20px;
}
button {
padding: 8px 16px;
background-color: #42b883;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #33a06f;
}
button.reset {
background-color: #ff7875;
}
button.reset:hover {
background-color: #f5222d;
}
</style>
Then convert it to use the Composition API with the <script setup> syntax.
Key Takeaways
- Vue is a progressive JavaScript framework for building user interfaces
- Core architecture includes a reactivity system, template compiler, and virtual DOM
- Single-File Components (SFCs) encapsulate template, script, and style in one file
- Vue 3 offers both the Options API and Composition API for component logic
- The Vue ecosystem includes official libraries for routing, state management, and more
- Vue is designed to be approachable, versatile, and performant
- Vite is the recommended tool for setting up modern Vue projects