Vue.js Tutorial
Vue.js Tutorial π
Welcome to the Vue.js Tutorial using the Chirpy theme for Jekyll! This guide covers Vue.js step-by-step, starting from basics to advanced concepts. Click on any topic to jump to that section.
π Table of Contents
1β£ Introduction to Vue.js
2β£ Setting Up Vue.js with Vite
- What is Vite?
- Why use Vite for Vue.js?
- Installing Vite and Creating a Vue Project
- Project Structure Overview
- Running the Development Server
3β£ Vue.js Fundamentals (Options API)
4β£ Template Syntax in Vue.js
- Interpolation (
\{\{ \}\}
) - Directives (
v-if
,v-show
,v-for
,v-bind
,v-model
) - Event Handling (
v-on
) - Attribute Binding (
v-bind
)
5β£ Vue Components
- Creating and Registering Components
- Props and Component Communication
- Dynamic Components
- Slots in Vue.js
- Parent-Child Communication
6β£ Computed Properties & Watchers
- Introduction to Computed Properties
- Getters and Setters in Computed Properties
- The Watch Property for Reactive Changes
7β£ Data Binding in Vue.js
8β£ Vue Directives
- Conditional Rendering (
v-if
,v-else
,v-show
) - List Rendering (v-for)
- Event Handling with v-on
- Two-Way Binding with V-model
9β£ Vue Router: Navigation & Routing
10 State Management in Vue.js
11 Vue.js and API Communication
12 Deploying a Vue App
π Happy Coding! π
1. Introduction to Vue.js
What is Vue.js?
Vue.js is a progressive JavaScript framework used for building user interfaces (UIs) and single-page applications (SPAs). It is designed to be incrementally adoptable, meaning you can use it for small components or scale it to large, complex applications.
Vue.js was created by Evan You and first released in 2014. Since then, it has gained popularity due to its ease of use, flexibility, and performance.
Key Highlights of Vue.js:
- Uses Declarative Rendering for efficient UI updates.
- Offers a reactive and composable data-binding system.
- Supports component-based architecture for modular development.
- Provides built-in directives for seamless DOM manipulation.
- Lightweight with a small footprint (~20 KB gzipped).
Features of Vue.js
Vue.js comes with a range of powerful features that make development fast and efficient:
Feature | Description |
---|---|
Reactive Data Binding | Automatically updates the DOM when data changes. |
Virtual DOM | Uses an optimized Virtual DOM for fast UI updates. |
Component-Based Architecture | Helps in building reusable UI components. |
Directives | Built-in directives like v-if , v-for , v-model simplify UI manipulation. |
Computed Properties & Watchers | Efficiently handle dependent data calculations and track changes. |
Vue Router | Enables seamless navigation in Single-Page Applications (SPAs). |
Vuex (State Management) | Centralized state management for large-scale applications. |
Transitions & Animations | Provides built-in support for animations and transitions. |
Lightweight & Fast | Small file size and optimized performance. |
Integrates Easily | Works well with other libraries and existing projects. |
Comparison with Other Frameworks
Vue.js is often compared with other frontend frameworks like React, Angular, Knockout.js, and Polymer. Below is a detailed comparison:
Vue.js vs React
Feature | Vue.js | React |
---|---|---|
Type | Framework | Library |
Syntax | Uses HTML-based templates | Uses JSX (JavaScript XML) |
State Management | Vuex (Official) | Redux, Context API, Recoil, Zustand |
Two-Way Binding | Supported with `v-model` | Requires manual handling |
Learning Curve | Easier to learn | Slightly steeper due to JSX and state management |
Performance | Fast with Virtual DOM | Fast with Virtual DOM |
Community Support | Growing, but smaller than React | Large and mature community |
Verdict: Vue.js is easier for beginners due to its HTML-like templates, while React provides more flexibility with JavaScript-driven development.
Vue.js vs Angular
Feature | Vue.js | Angular |
---|---|---|
Type | Progressive Framework | Full-fledged Framework |
Language | JavaScript | TypeScript |
Architecture | Component-based | Component-based with MVC pattern |
Size | ~20KB (small) | ~500KB (large) |
Performance | Faster due to Virtual DOM | Slightly slower due to real DOM manipulations |
Learning Curve | Easier | Steep, due to TypeScript and complex concepts |
Data Binding | Two-way with `v-model` | Two-way with `ngModel` |
Usage | Flexible for small & large projects | Best for large enterprise applications |
Verdict: Vue.js is lighter and easier to learn, while Angular is feature-rich and structured, making it suitable for enterprise applications.
Vue.js vs Knockout.js
Feature | Vue.js | Knockout.js |
---|---|---|
Type | Modern UI Framework | MVVM-based Library |
Reactive System | Built-in reactivity | Uses observables for reactivity |
Component-Based | Yes | No |
Performance | Fast with Virtual DOM | Slower compared to modern frameworks |
Popularity | Growing rapidly | Declining usage |
Verdict: Knockout.js is an older library primarily used for legacy applications, while Vue.js is a modern alternative with better community support.
Vue.js vs Polymer
Feature | Vue.js | Polymer |
---|---|---|
Type | JavaScript Framework | Library for Web Components |
Approach | Component-based UI | Web Components (custom elements) |
Performance | Faster Virtual DOM | Uses real DOM, can be slower |
Adoption | Widely used | Niche usage, mainly for Web Components |
Verdict: Vue.js is more practical for building modern web applications, while Polymer is better suited for custom Web Components.
Conclusion
Vue.js is a powerful, lightweight, and flexible JavaScript framework that combines the best features of React and Angular. It is an excellent choice for beginners and experienced developers looking to build scalable, high-performance web applications.
This section provides a clear introduction to Vue.js and how it compares to other frameworks. Let me know if you need modifications or additional details! π
2. Setting Up Vue.js with Vite
What is Vite?
Vite (pronounced βveetβ) is a next-generation build tool that provides fast and optimized development environments for modern web applications. It was created by Evan You, the creator of Vue.js.
Key Features of Vite:
- Lightning-fast Hot Module Replacement (HMR) β Instant updates without reloading the page.
- On-Demand Compilation β Compiles only the necessary files, improving speed.
- Optimized Build β Uses Rollup for production-ready builds.
- TypeScript & JSX Support β Built-in support for TypeScript, JSX, and CSS Preprocessors.
- ES Module-based Development β No need for bundling during development.
Why Use Vite for Vue.js?
Vite is the recommended way to set up Vue 3 projects because it overcomes the performance issues of traditional build tools like Webpack.
Feature | Vite | Webpack |
---|---|---|
Startup Speed | Instant (No bundling) | Slow (Bundling required) |
Hot Module Replacement (HMR) | Fast | Slow |
Build Performance | Optimized with Rollup | Can be slow for large projects |
Configuration | Minimal | Complex |
ES Module Support | Yes | No |
Verdict: Vite provides a superior development experience with faster updates, fewer configurations, and better performance.
Installing Vite and Creating a Vue Project
Setting up a Vue.js project with Vite is simple and quick. Follow these steps:
Step 1: Install Node.js
Ensure you have Node.js (v16 or later) installed. You can check your version using:
1
node -v
If you donβt have Node.js, download it from nodejs.org.
Step 2: Create a Vue Project with Vite
Run the following command to create a new Vue.js project using Vite:
1
npm create vite@latest my-vue-app
or using Yarn:
1
yarn create vite@latest my-vue-app
Youβll be prompted to select a framework. Choose Vue and then select JavaScript or TypeScript.
1
2
β Select a framework: βΊ Vue
β Select a variant: βΊ JavaScript / TypeScript
This will generate a new Vue.js project in the my-vue-app
directory.
Step 3: Install Dependencies
Navigate to your project folder and install dependencies:
1
2
cd my-vue-app
npm install
or using Yarn:
1
2
cd my-vue-app
yarn install
Project Structure Overview
Once your project is created, the folder structure will look like this:
1
2
3
4
5
6
7
8
9
10
11
12
my-vue-app/
βββ node_modules/ # Installed dependencies
βββ public/ # Static assets (favicon, images, etc.)
βββ src/ # Main application code
β βββ assets/ # Static assets (CSS, images)
β βββ components/ # Vue components
β βββ App.vue # Root component
β βββ main.js # Entry point
βββ index.html # Main HTML file
βββ package.json # Project configuration
βββ vite.config.js # Vite configuration
βββ README.md # Project documentation
Key Files:
index.html
β Main HTML entry point.src/main.js
β Application entry file.src/App.vue
β Root component.vite.config.js
β Vite configuration file.
Running the Development Server
Once everything is set up, start the development server:
1
npm run dev
or using Yarn:
1
yarn dev
This will start a local development server with hot module replacement (HMR). Youβll see output like:
1
2
VITE v4.0.0 ready in 100ms
β Local: http://localhost:5173/
Open http://localhost:5173/ in your browser to see your Vue app running.
Conclusion
Setting up Vue.js with Vite is fast and efficient. Vite provides an optimized development experience with instant startup times, lightning-fast HMR, and minimal configurations. Now that your project is up and running, you can start building Vue.js applications with ease! π
3. Vue.js Fundamentals (Options API)
Introduction to the Options API
The Options API is the traditional way of writing Vue components, where all the logic is organized using different option properties inside a Vue instance. This approach is useful for developers transitioning from Vue 2 and is widely used in projects that prioritize readability and maintainability.
Key Features of the Options API:
- Uses object-based configuration.
- Organizes logic into specific sections (e.g.,
data
,methods
,computed
,watch
). - Suitable for small to medium-sized applications.
- More structured and easy to understand.
Basic Example of the Options API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
export default {
data() {
return {
message: "Hello, Vue!",
};
},
methods: {
greet() {
return `Welcome! ${this.message}`;
},
},
};
</script>
<template>
<div>
<h1>\{\{ message \}\}</h1>
<button @click="greet">Click Me</button>
</div>
</template>
Understanding Vue Instances (new Vue()
)
In Vue.js, everything starts with creating a Vue instance, which is responsible for data management, rendering, and event handling.
Creating a Vue Instance
Before Vue 3 introduced the Composition API, Vue 2 relied on creating an instance using new Vue()
:
1
2
3
4
5
6
new Vue({
el: "#app",
data: {
message: "Hello Vue!",
},
});
el
: The element where Vue will mount.data
: The reactive data object.
Vue 3 Equivalent
In Vue 3, we use createApp()
instead of new Vue()
:
1
2
3
4
import { createApp } from "vue";
import App from "./App.vue";
createApp(App).mount("#app");
The Vue Lifecycle Hooks
Vue provides lifecycle hooks that allow you to execute logic at different stages of a componentβs lifecycle.
Lifecycle Hook | Description |
---|---|
beforeCreate() | Called before data observation and event setup. |
created() | Called after data observation and events are initialized. |
beforeMount() | Called before the component is added to the DOM. |
mounted() | Called when the component is inserted into the DOM. |
beforeUpdate() | Called before re-rendering when reactive data changes. |
updated() | Called after the component re-renders due to data changes. |
beforeUnmount() | Called before a component is destroyed. |
unmounted() | Called after the component is removed from the DOM. |
Example: Using Lifecycle Hooks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<script>
export default {
data() {
return {
message: "Hello Vue!",
};
},
beforeCreate() {
console.log("beforeCreate: Data is not yet reactive.");
},
created() {
console.log("created: Data is now reactive.");
},
beforeMount() {
console.log("beforeMount: Template is compiled.");
},
mounted() {
console.log("mounted: Component is now in the DOM.");
},
beforeUpdate() {
console.log("beforeUpdate: Data is changing.");
},
updated() {
console.log("updated: The DOM has been updated.");
},
beforeUnmount() {
console.log("beforeUnmount: Component is about to be destroyed.");
},
unmounted() {
console.log("unmounted: Component is removed from the DOM.");
},
};
</script>
<template>
<div>
<h1>\{\{ message \}\}</h1>
<button @click="message = 'Vue Lifecycle Updated!'">Update Message</button>
</div>
</template>
Conclusion
The Options API provides a structured way to manage Vue applications. Understanding Vue instances and lifecycle hooks helps in controlling how components behave during their creation, updating, and destruction. Mastering these concepts is essential for building robust Vue applications! π
Hereβs the content for 4. Template Syntax in Vue.js:
4. Template Syntax in Vue.js
Vue.js uses an HTML-based template syntax that allows us to declaratively bind the rendered DOM to the underlying componentβs data. This template syntax is intuitive and provides powerful directives for dynamic rendering.
Interpolation (\{\{ \}\}
)
Interpolation is used to dynamically insert data into HTML templates using double curly braces (\{\{ \}\}
).
Example of Interpolation:
1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<h1>\{\{ message \}\}</h1>
</template>
<script>
export default {
data() {
return {
message: "Hello, Vue.js!",
};
},
};
</script>
π How it works:
- The
\{\{ message \}\}
placeholder is replaced by"Hello, Vue.js!"
. - Vue automatically updates the text whenever
message
changes.
β
Can we use JavaScript expressions inside \{\{ \}\}
?
Yes! You can use simple expressions:
1
2
3
4
<template>
<h1>\{\{ message.toUpperCase() \}\}</h1>
<p>2 + 2 = \{\{ 2 + 2 \}\}</p>
</template>
β Cannot use statements like if
or for
inside \{\{ \}\}
.
Directives (v-if
, v-show
, v-for
, v-bind
, v-model
)
Vue directives are special attributes prefixed with v-
, which allow us to manipulate the DOM dynamically.
Conditional Rendering (v-if
, v-show
)
v-if
and v-show
are used for conditionally displaying elements.
Using v-if
v-if
completely removes or adds elements based on a condition.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<p v-if="isVisible">This text is visible</p>
<button @click="isVisible = !isVisible">Toggle Visibility</button>
</template>
<script>
export default {
data() {
return {
isVisible: true,
};
},
};
</script>
π v-if
removes the element from the DOM when false.
Using v-show
v-show
toggles the CSS display
property instead of removing elements.
1
<p v-show="isVisible">This text is visible</p>
β When to use?
v-if
β When elements should be completely added/removed.v-show
β When frequent toggling is needed.
List Rendering (v-for
)
v-for
is used to render lists dynamically.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<ul>
<li v-for="(item, index) in items" :key="index">
\{\{ index + 1 \}\}. \{\{ item \}\}
</li>
</ul>
</template>
<script>
export default {
data() {
return {
items: ["Vue", "React", "Angular"],
};
},
};
</script>
π Important:
- Always use a
key
attribute for better performance. item
represents the current value, andindex
is the current position.
Attribute Binding (v-bind
)
v-bind
dynamically binds attributes to elements.
Example: Binding a src
attribute
1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<img v-bind:src="imageUrl" alt="Vue Logo" />
</template>
<script>
export default {
data() {
return {
imageUrl: "https://vuejs.org/images/logo.png",
};
},
};
</script>
π Shortcut: You can omit v-bind:
and just use :
1
<img :src="imageUrl" alt="Vue Logo" />
Two-Way Data Binding (v-model
)
v-model
creates a two-way binding between a form input and the component data.
Example: Using v-model
with Input Fields
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<input v-model="name" placeholder="Enter your name" />
<p>Hello, \{\{ name \}\}!</p>
</template>
<script>
export default {
data() {
return {
name: "",
};
},
};
</script>
π v-model
automatically updates name
whenever the user types.
Event Handling (v-on
)
Vue provides v-on
to listen for DOM events and trigger methods.
Example: Handling Click Events
1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<button v-on:click="greet">Click Me</button>
</template>
<script>
export default {
methods: {
greet() {
alert("Hello from Vue!");
},
},
};
</script>
π Shortcut:
v-on
can be shortened to @
:
1
<button @click="greet">Click Me</button>
Conclusion
Vueβs template syntax provides powerful tools like interpolation, directives, and event handling, making dynamic UI development easy. Understanding these features is crucial for mastering Vue.js! π
5. Vue Components
Vue components are the building blocks of a Vue application. They allow you to create reusable, modular UI elements, making your application scalable and maintainable.
Creating and Registering Components
There are two ways to create and register components in Vue.js:
- Global Registration β The component is available throughout the application.
- Local Registration β The component is available only within the parent component.
1. Global Registration
A globally registered component can be used anywhere in the app.
Example: Registering a Global Component
1
2
3
4
5
6
7
8
9
10
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App);
app.component("HelloComponent", {
template: `<h1>Hello from Global Component!</h1>`,
});
app.mount("#app");
Now you can use <HelloComponent />
anywhere in the templates.
2. Local Registration
A locally registered component is scoped to a specific component.
Example: Registering a Local Component
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- ParentComponent.vue -->
<template>
<ChildComponent />
</template>
<script>
import ChildComponent from "./ChildComponent.vue";
export default {
components: {
ChildComponent,
},
};
</script>
Props and Component Communication
Props allow data passing from a parent component to a child component.
Using Props
Props are custom attributes that a component can accept.
Example: Passing Props
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- ParentComponent.vue -->
<template>
<ChildComponent message="Hello from Parent!" />
</template>
<script>
import ChildComponent from "./ChildComponent.vue";
export default {
components: {
ChildComponent,
},
};
</script>
1
2
3
4
5
6
7
8
9
10
<!-- ChildComponent.vue -->
<template>
<p>\{\{ message \}\}</p>
</template>
<script>
export default {
props: ["message"],
};
</script>
π Key Notes:
- Props should be read-only inside the child component.
- You can validate props with type checking:
1 2 3 4 5 6
props: { message: { type: String, required: true, }, }
Dynamic Components
Dynamic components allow swapping components dynamically using the component
tag.
Example: Switching Components Dynamically
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<button @click="currentComponent = 'ComponentA'">Show A</button>
<button @click="currentComponent = 'ComponentB'">Show B</button>
<component :is="currentComponent"></component>
</template>
<script>
import ComponentA from "./ComponentA.vue";
import ComponentB from "./ComponentB.vue";
export default {
data() {
return {
currentComponent: "ComponentA",
};
},
components: {
ComponentA,
ComponentB,
},
};
</script>
π :is="currentComponent"
dynamically renders the selected component.
Slots in Vue.js
Slots allow content projection, meaning a parent can pass content inside a child component.
1. Default Slot
A default slot allows passing content into the child component.
Example: Using Default Slot
1
2
3
4
<!-- ParentComponent.vue -->
<ChildComponent>
<p>This is content from the parent!</p>
</ChildComponent>
1
2
3
4
5
6
7
<!-- ChildComponent.vue -->
<template>
<div>
<h3>Child Component</h3>
<slot></slot> <!-- This is where content will be injected -->
</div>
</template>
2. Named Slots
Named slots allow passing multiple sections of content.
Example: Using Named Slots
1
2
3
4
5
6
7
8
9
<!-- ParentComponent.vue -->
<ChildComponent>
<template v-slot:header>
<h1>Header Content</h1>
</template>
<template v-slot:footer>
<p>Footer Content</p>
</template>
</ChildComponent>
1
2
3
4
5
6
7
8
<!-- ChildComponent.vue -->
<template>
<div>
<slot name="header"></slot>
<p>Main content of child component</p>
<slot name="footer"></slot>
</div>
</template>
Parent-Child Communication
Vue supports parent-child communication through:
- Props β From parent to child.
- Events (
$emit
) β From child to parent.
1. Passing Data from Parent to Child (via Props)
As shown earlier, props are used for parent-to-child data communication.
2. Emitting Events from Child to Parent ($emit
)
If a child needs to send data to the parent, it uses $emit()
.
Example: Child Component Sending Data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- ChildComponent.vue -->
<template>
<button @click="sendMessage">Send Message</button>
</template>
<script>
export default {
methods: {
sendMessage() {
this.$emit("messageEvent", "Hello from Child!");
},
},
};
</script>
Example: Parent Component Handling Event
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- ParentComponent.vue -->
<template>
<ChildComponent @messageEvent="handleMessage" />
<p>\{\{ receivedMessage \}\}</p>
</template>
<script>
import ChildComponent from "./ChildComponent.vue";
export default {
components: { ChildComponent },
data() {
return {
receivedMessage: "",
};
},
methods: {
handleMessage(msg) {
this.receivedMessage = msg;
},
},
};
</script>
π The child emits an event, and the parent listens for it using @messageEvent="handleMessage"
.
Conclusion
Vue components allow modular development by breaking down the UI into reusable elements. Understanding props, slots, dynamic components, and event communication is key to building scalable Vue applications. π
6. Computed Properties & Watchers
Vue.js provides computed properties and watchers to handle reactive data efficiently. These tools help optimize performance by avoiding unnecessary function calls and allowing reactive updates based on data changes.
Introduction to Computed Properties
Computed properties are cached values that update only when their dependencies change. Unlike methods, computed properties do not re-run every time the template re-renders.
Key Features of Computed Properties:
β
Efficient: They are cached and recomputed only when their dependencies change.
β
Declarative: Allows defining derived state based on existing data.
β
Readability: Helps keep templates clean and maintainable.
Example: Using Computed Properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<p>Original Message: \{\{ message \}\}</p>
<p>Reversed Message: \{\{ reversedMessage \}\}</p>
</template>
<script>
export default {
data() {
return {
message: "Hello Vue!",
};
},
computed: {
reversedMessage() {
return this.message.split("").reverse().join("");
},
},
};
</script>
π Here, reversedMessage
is a computed property that depends on message
.
π‘ Advantage over Methods: Unlike a method, reversedMessage
is only recomputed when message
changes.
Getters and Setters in Computed Properties
Computed properties can have getters and setters, allowing custom logic when accessing or updating a value.
Example: Computed Getters and Setters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
<p>Full Name: \{\{ fullName \}\}</p>
<input v-model="fullName" placeholder="Enter full name" />
</template>
<script>
export default {
data() {
return {
firstName: "John",
lastName: "Doe",
};
},
computed: {
fullName: {
get() {
return `${this.firstName} ${this.lastName}`;
},
set(newValue) {
const names = newValue.split(" ");
this.firstName = names[0];
this.lastName = names[1] || "";
},
},
},
};
</script>
π How it works:
- Getter (
get
): CombinesfirstName
andlastName
intofullName
. - Setter (
set
): SplitsfullName
intofirstName
andlastName
when modified.
π‘ This is useful for form handling where you need bi-directional data binding.
The Watch Property for Reactive Changes
Watchers in Vue observe changes in data and execute logic when a value changes.
Key Features of Watchers
β
Useful for asynchronous operations (e.g., API calls).
β
Runs custom logic when a reactive property changes.
β
Ideal for triggering side effects when data changes.
Example: Using a Watcher
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<p>Number: \{\{ number \}\}</p>
<button @click="number++">Increase</button>
<p>\{\{ status \}\}</p>
</template>
<script>
export default {
data() {
return {
number: 0,
status: "Waiting...",
};
},
watch: {
number(newVal, oldVal) {
if (newVal > 5) {
this.status = "Number is greater than 5!";
} else {
this.status = "Waiting...";
}
},
},
};
</script>
π How it works:
- The
watch
property tracks changes innumber
. - When
number
exceeds 5,status
updates accordingly.
π‘ When to use Watchers?
- Watching API responses (e.g., fetching data when a search query changes).
- Triggering expensive computations when a value changes.
- Observing multiple dependencies dynamically.
Deep Watching
By default, Vue watchers do not track nested objects. You can use { deep: true }
to watch deep objects.
1
2
3
4
5
6
7
8
watch: {
user: {
handler(newValue) {
console.log("User data changed:", newValue);
},
deep: true,
},
}
Computed Properties vs. Watchers
| Feature | Computed Properties | Watchers | |βββ|βββββββ|βββ-| | Best for | Derived state based on existing data | Performing actions when data changes | | Performance | Cached, only recalculates when dependencies change | Runs every time the watched property changes | | Use Case | Formatting data, filtering, transformations | Fetching API data, logging changes, executing logic on change |
Conclusion
- Computed properties allow efficient state derivation and auto-update only when needed.
- Getters and setters provide advanced data manipulation in computed properties.
- Watchers help trigger side effects like API calls, making Vue highly reactive.
Mastering these features will help in building high-performance Vue.js applications! π
7. Data Binding in Vue.js
Vue.js provides data binding mechanisms that allow you to connect HTML elements with JavaScript data, making applications dynamic and reactive. There are two main types of data binding: one-way and two-way.
One-Way vs. Two-Way Data Binding
Data binding determines how data flows between the component and the DOM.
Type | Description | Example |
---|---|---|
One-Way Binding | Data flows from the component to the DOM. Changes in the DOM do not affect the data in the component. | v-bind |
Two-Way Binding | Data flows both ways between the component and the DOM. Changes in the input field update the Vue data, and vice versa. | v-model |
Example: One-Way Binding (v-bind
)
One-way binding is useful when displaying read-only or dynamic values in the template.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<p>Message: \{\{ message \}\}</p>
<input :value="message" />
</template>
<script>
export default {
data() {
return {
message: "Hello Vue!",
};
},
};
</script>
π Changing the input field will NOT update message
because the data is bound in one direction.
Example: Two-Way Binding (v-model
)
Two-way binding is useful for forms and user inputs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<input v-model="message" />
<p>Typed: \{\{ message \}\}</p>
</template>
<script>
export default {
data() {
return {
message: "Hello Vue!",
};
},
};
</script>
π Changing the input field WILL update message
because the data is bound in both directions.
Binding HTML Classes & Styles
Vue allows binding CSS classes and inline styles dynamically.
Binding CSS Classes
We can bind CSS classes dynamically using v-bind:class
(or simply :class
).
Example: Dynamic Class Binding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<p :class="{ active: isActive, disabled: !isActive }">Dynamic Class</p>
<button @click="isActive = !isActive">Toggle Class</button>
</template>
<script>
export default {
data() {
return {
isActive: true,
};
},
};
</script>
<style>
.active {
color: green;
}
.disabled {
color: red;
}
</style>
π The class toggles between βactiveβ and βdisabledβ when clicking the button.
Binding Inline Styles
We can bind styles dynamically using v-bind:style
(or :style
).
Example: Dynamic Style Binding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<p :style="{ color: textColor, fontSize: fontSize + 'px' }">Styled Text</p>
<button @click="textColor = 'blue'">Change Color</button>
</template>
<script>
export default {
data() {
return {
textColor: "red",
fontSize: 20,
};
},
};
</script>
π Clicking the button changes the text color dynamically.
Handling Forms with v-model
Vue provides v-model
for seamless form handling. It supports different input types such as:
- Text fields
- Checkboxes
- Radio buttons
- Dropdowns (Select)
1. Text Input Binding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<input v-model="name" placeholder="Enter your name" />
<p>Hello, \{\{ name \}\}!</p>
</template>
<script>
export default {
data() {
return {
name: "",
};
},
};
</script>
π Typing in the input field updates name
in real time.
2. Checkbox Binding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<input type="checkbox" v-model="isChecked" />
<p>Checkbox is: \{\{ isChecked ? "Checked" : "Unchecked" \}\}</p>
</template>
<script>
export default {
data() {
return {
isChecked: false,
};
},
};
</script>
π The checkbox state (true/false
) is synced with isChecked
.
3. Radio Button Binding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<label><input type="radio" v-model="gender" value="Male" /> Male</label>
<label><input type="radio" v-model="gender" value="Female" /> Female</label>
<p>Selected: \{\{ gender \}\}</p>
</template>
<script>
export default {
data() {
return {
gender: "",
};
},
};
</script>
π Only one radio button can be selected at a time.
4. Dropdown (Select) Binding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<select v-model="selectedFruit">
<option value="Apple">Apple</option>
<option value="Banana">Banana</option>
<option value="Orange">Orange</option>
</select>
<p>Selected: \{\{ selectedFruit \}\}</p>
</template>
<script>
export default {
data() {
return {
selectedFruit: "",
};
},
};
</script>
π Selecting an option updates selectedFruit
dynamically.
Conclusion
- One-way binding (
v-bind
) is used for static or computed data. - Two-way binding (
v-model
) is best for forms and user inputs. - Class and style binding allows for dynamic UI updates.
- Vueβs reactive data binding makes it easy to build interactive applications.
Master these concepts to enhance your Vue development skills! π
8. Vue Directives
Vue directives are special prefixes with v-
that apply reactivity and behavior to HTML elements. They are an essential part of Vue.js and help in managing DOM updates efficiently.
1. Conditional Rendering (v-if
, v-else
, v-show
)
Conditional rendering allows elements to be displayed or removed from the DOM based on conditions.
v-if
& v-else
(Full DOM Removal)
v-if
adds or removes elements from the DOM based on a condition.
Example: Using v-if
and v-else
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<p v-if="isLoggedIn">Welcome, User!</p>
<p v-else>Please log in.</p>
<button @click="isLoggedIn = !isLoggedIn">Toggle Login</button>
</template>
<script>
export default {
data() {
return {
isLoggedIn: false,
};
},
};
</script>
π v-if
completely removes the element from the DOM when false
.
v-show
(CSS-Based Visibility)
Unlike v-if
, v-show
hides elements using CSS (display: none;
) instead of removing them from the DOM.
Example: Using v-show
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<p v-show="isVisible">This text is always in the DOM but may be hidden.</p>
<button @click="isVisible = !isVisible">Toggle Visibility</button>
</template>
<script>
export default {
data() {
return {
isVisible: true,
};
},
};
</script>
π v-show
is useful when frequent toggling is needed.
Comparison: v-if
vs v-show
Feature | v-if | v-show |
---|---|---|
Behavior | Adds/removes from the DOM | Hides using CSS (display: none; ) |
Performance | Better for rarely changed elements | Better for frequently toggled elements |
Initial Rendering | Higher cost | Lower cost |
β
Use v-if
for rarely toggled elements (better performance).
β
Use v-show
for frequently toggled elements (avoids expensive DOM re-renders).
2. List Rendering (v-for
)
v-for
is used to dynamically render lists based on an array.
Example: Looping Through an Array
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<ul>
<li v-for="(item, index) in items" :key="index">
\{\{ index + 1 \}\}. \{\{ item \}\}
</li>
</ul>
</template>
<script>
export default {
data() {
return {
items: ["Vue", "React", "Angular"],
};
},
};
</script>
π Always use :key
for better performance and to help Vue track elements efficiently.
Looping Over Objects
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<ul>
<li v-for="(value, key) in user" :key="key">
\{\{ key \}\}: \{\{ value \}\}
</li>
</ul>
</template>
<script>
export default {
data() {
return {
user: { name: "John", age: 30, country: "USA" },
};
},
};
</script>
π Vue provides value, key, and index when looping through objects.
Looping a Set Number of Times
You can use v-for
to repeat an element a set number of times.
1
2
3
<template>
<p v-for="n in 5" :key="n">This is item \{\{ n \}\}</p>
</template>
π Loops from 1
to 5
dynamically.
3. Event Handling (v-on
)
Vue uses v-on
to listen for DOM events and execute functions.
Example: Handling Click Events
1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<button v-on:click="greet">Click Me</button>
</template>
<script>
export default {
methods: {
greet() {
alert("Hello from Vue!");
},
},
};
</script>
π Shortcut:
v-on
can be shortened to @
:
1
<button @click="greet">Click Me</button>
Passing Event Data
1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<button @click="sayHello('Vue')">Say Hello</button>
</template>
<script>
export default {
methods: {
sayHello(name) {
alert(`Hello, ${name}!`);
},
},
};
</script>
π Using $event
to Access Event Object
1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<input @keyup="handleKey($event)" />
</template>
<script>
export default {
methods: {
handleKey(event) {
console.log("Key Pressed:", event.key);
},
},
};
</script>
π Event Modifiers (@click.prevent
, @keyup.enter
)
1
2
<button @click.prevent="submitForm">Submit</button> <!-- Prevent default action -->
<input @keyup.enter="submitForm" /> <!-- Only triggers on Enter key -->
4. Two-Way Binding (v-model
)
v-model
creates a two-way binding between input fields and data.
Example: Text Input Binding
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<input v-model="message" placeholder="Type something" />
<p>You typed: \{\{ message \}\}</p>
</template>
<script>
export default {
data() {
return {
message: "",
};
},
};
</script>
π The input field is synchronized with message
.
Handling Checkboxes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<input type="checkbox" v-model="isChecked" />
<p>Checkbox is: \{\{ isChecked ? "Checked" : "Unchecked" \}\}</p>
</template>
<script>
export default {
data() {
return {
isChecked: false,
};
},
};
</script>
Handling Radio Buttons
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<label><input type="radio" v-model="gender" value="Male" /> Male</label>
<label><input type="radio" v-model="gender" value="Female" /> Female</label>
<p>Selected: \{\{ gender \}\}</p>
</template>
<script>
export default {
data() {
return {
gender: "",
};
},
};
</script>
Handling Select Dropdowns
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<select v-model="selectedFruit">
<option value="Apple">Apple</option>
<option value="Banana">Banana</option>
<option value="Orange">Orange</option>
</select>
<p>Selected: \{\{ selectedFruit \}\}</p>
</template>
<script>
export default {
data() {
return {
selectedFruit: "",
};
},
};
</script>
Conclusion
- Conditional Rendering:
v-if
removes elements from the DOM, whilev-show
hides them. - List Rendering:
v-for
dynamically creates lists. - Event Handling:
v-on
(@
) listens for events. - Two-Way Binding:
v-model
keeps inputs and data in sync.
Mastering Vue directives will make your applications more reactive and dynamic! π
9. Vue Router: Navigation & Routing
Vue Router is the official routing library for Vue.js, enabling single-page applications (SPAs) to navigate between different views without reloading the page.
1. Setting Up Vue Router
To use Vue Router in a Vue 3 project, follow these steps:
Step 1: Install Vue Router
Run the following command in your project:
1
npm install vue-router@4
π Vue Router 4 is compatible with Vue 3.
Step 2: Create the Router Configuration
Inside the src
folder, create a new file: src/router/index.js
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { createRouter, createWebHistory } from "vue-router";
import Home from "../views/Home.vue";
import About from "../views/About.vue";
const routes = [
{ path: "/", component: Home },
{ path: "/about", component: About },
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
π This defines two routes:
/
β Loads Home.vue/about
β Loads About.vue
Step 3: Register the Router in main.js
Modify src/main.js
to use the router.
1
2
3
4
5
6
7
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router"; // Import router
const app = createApp(App);
app.use(router);
app.mount("#app");
Step 4: Add Router View in App.vue
Replace the contents of src/App.vue
with:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<nav>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</nav>
<router-view></router-view>
</template>
<style>
nav {
display: flex;
gap: 15px;
}
</style>
π <router-link>
β Creates navigational links.
π <router-view>
β Displays the active page.
β Now, Vue Router is fully set up! π
2. Defining Routes and Route Parameters
Routes can have dynamic parameters that help in building dynamic pages.
Dynamic Route Parameters
1
2
3
const routes = [
{ path: "/user/:id", component: UserProfile },
];
π :id
is a dynamic route parameter.
Accessing Route Parameters in a Component
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<h2>User ID: \{\{ userId \}\}</h2>
</template>
<script>
import { useRoute } from "vue-router";
export default {
setup() {
const route = useRoute();
return {
userId: route.params.id,
};
},
};
</script>
π The useRoute()
function gives access to the route parameters.
Programmatic Navigation
You can navigate to a new route dynamically using $router.push()
.
Example: Redirecting Users
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<button @click="goToProfile">Go to Profile</button>
</template>
<script>
import { useRouter } from "vue-router";
export default {
setup() {
const router = useRouter();
function goToProfile() {
router.push("/user/123");
}
return { goToProfile };
},
};
</script>
π Clicking the button navigates to /user/123
.
3. Navigation Guards
Navigation Guards allow you to control access to specific routes.
Types of Navigation Guards
| Guard | Description | |ββ-|ββββ| | beforeEach
| Runs before every navigation. | | beforeResolve
| Runs before resolving navigation. | | afterEach
| Runs after navigation completes. |
Example: Protecting Routes
Modify router/index.js
:
1
2
3
4
5
6
7
8
9
router.beforeEach((to, from, next) => {
const isAuthenticated = false; // Change this based on auth state
if (to.path === "/dashboard" && !isAuthenticated) {
next("/login"); // Redirect to login if not authenticated
} else {
next(); // Continue to the requested page
}
});
π If a user tries to access /dashboard
without authentication, they are redirected to /login
.
Guarding a Specific Route in beforeEnter
1
2
3
4
5
6
7
8
9
10
const routes = [
{
path: "/admin",
component: AdminPage,
beforeEnter: (to, from, next) => {
if (!isAdmin) next("/"); // Redirect non-admin users
else next();
},
},
];
π This guards only the /admin
page.
Conclusion
- Vue Router enables SPAs by managing navigation without page reloads.
- Use dynamic route parameters (
:id
) for dynamic pages. - Navigation Guards (
beforeEach
) help in authentication and access control.
By mastering Vue Router, you can build powerful, scalable applications! π
10. State Management in Vue.js
Vue.js provides state management solutions to handle shared data efficiently across components. The most common state management tool in Vue is Vuex, but Vue 3 also introduced Pinia as a modern alternative.
1. Introduction to Vuex
Vuex is a centralized state management library for Vue applications. It follows the Flux architecture, ensuring that state updates are predictable and trackable.
Why Use Vuex?
β
Centralized State β Stores application-wide data in a single place.
β
Predictable Mutations β Ensures that state changes are explicit and traceable.
β
Component Communication β Allows cross-component data sharing without prop drilling.
β
DevTools Support β Integrates with Vue DevTools for state debugging.
2. Managing State with Vuex
Step 1: Install Vuex
Run the following command in your Vue 3 project:
1
npm install vuex@next
π @next
ensures compatibility with Vue 3.
Step 2: Create a Vuex Store
Inside your src
folder, create a new file: src/store/index.js
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { createStore } from "vuex";
const store = createStore({
state: {
count: 0, // Centralized state variable
},
mutations: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
},
},
actions: {
asyncIncrement({ commit }) {
setTimeout(() => {
commit("increment");
}, 1000);
},
},
getters: {
doubleCount(state) {
return state.count * 2;
},
},
});
export default store;
π Breakdown of Vuex Store:
state
β Stores the applicationβs global state.mutations
β Functions that directly modify state.actions
β Asynchronous operations that commit mutations.getters
β Computed properties for the state.
Step 3: Register Vuex in main.js
Modify src/main.js
to use Vuex.
1
2
3
4
5
6
7
import { createApp } from "vue";
import App from "./App.vue";
import store from "./store"; // Import Vuex store
const app = createApp(App);
app.use(store);
app.mount("#app");
3. Mutations, Actions, and Getters
Mutations (Synchronous State Changes)
Mutations directly modify the Vuex state.
Example: Committing a Mutation
1
2
3
4
5
<template>
<p>Count: \{\{ $store.state.count \}\}</p>
<button @click="$store.commit('increment')">Increment</button>
<button @click="$store.commit('decrement')">Decrement</button>
</template>
π Commiting a Mutation β $store.commit('mutationName')
.
Actions (Asynchronous Operations)
Actions are used for API calls or delayed state changes.
Example: Dispatching an Action
1
2
3
<template>
<button @click="$store.dispatch('asyncIncrement')">Async Increment</button>
</template>
π Dispatching an Action β $store.dispatch('actionName')
.
Getters (Computed State)
Getters compute derived state based on existing state.
Example: Using a Getter
1
2
3
<template>
<p>Double Count: \{\{ $store.getters.doubleCount \}\}</p>
</template>
π Accessing a Getter β $store.getters.getterName
.
Conclusion
- Vuex centralizes state and makes it accessible to all components.
- Mutations modify state synchronously.
- Actions handle asynchronous operations before committing mutations.
- Getters compute derived state.
By mastering Vuex, you can manage complex application states efficiently! π
11. Vue.js and API Communication
Vue.js allows easy API communication using libraries like Axios. Fetching data from APIs, handling responses, and managing errors are essential for building dynamic applications.
1. Fetching Data using Axios
Axios is a popular HTTP client for making API requests in Vue.js applications.
Step 1: Install Axios
Run the following command in your Vue project:
1
npm install axios
Step 2: Making a GET Request
Create a component that fetches data from an API using Axios.
Example: Fetching Data from an API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<div>
<h2>Users List</h2>
<ul>
<li v-for="user in users" :key="user.id">\{\{ user.name \}\}</li>
</ul>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
users: [],
};
},
async created() {
try {
const response = await axios.get("https://jsonplaceholder.typicode.com/users");
this.users = response.data;
} catch (error) {
console.error("Error fetching data:", error);
}
},
};
</script>
π How it works:
- Axios fetches data inside the
created()
lifecycle hook. - Data is stored in the
users
array. v-for
renders the fetched users dynamically.
2. Handling API Calls and Responses
Making a POST Request
To send data to an API, use POST requests.
Example: Sending Data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
<div>
<input v-model="newUser" placeholder="Enter name" />
<button @click="addUser">Add User</button>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
newUser: "",
};
},
methods: {
async addUser() {
try {
const response = await axios.post("https://jsonplaceholder.typicode.com/users", {
name: this.newUser,
});
console.log("User added:", response.data);
} catch (error) {
console.error("Error adding user:", error);
}
},
},
};
</script>
π The POST request sends newUser
to the API.
3. Managing Loading States and Errors
APIs can take time to respond, so we need loading indicators and error handling.
Example: Displaying Loading and Error Messages
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<template>
<div>
<h2>Users List</h2>
<p v-if="loading">Loading...</p>
<p v-if="error">\{\{ error \}\}</p>
<ul v-if="!loading && !error">
<li v-for="user in users" :key="user.id">\{\{ user.name \}\}</li>
</ul>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
users: [],
loading: true,
error: "",
};
},
async created() {
try {
const response = await axios.get("https://jsonplaceholder.typicode.com/users");
this.users = response.data;
} catch (err) {
this.error = "Failed to load data.";
} finally {
this.loading = false;
}
},
};
</script>
π Loading (loading
state) shows a message while data is being fetched.
π Error handling (error
state) displays an error message if the API fails.
Conclusion
- Axios simplifies API communication in Vue.js.
- GET and POST requests are commonly used for fetching and sending data.
- Loading and error states improve the user experience.
By mastering API communication, you can build powerful, real-world Vue applications! π
12. Deploying a Vue App
Once your Vue.js application is complete, the final step is deploying it for public access. Vue apps can be deployed on platforms like Netlify, Vercel, and GitHub Pages with ease.
1. Building for Production
Before deploying, you need to build your Vue project into optimized static files.
Step 1: Run the Build Command
1
npm run build
This command generates an optimized dist/
folder containing:
- Minified JavaScript and CSS files.
- Optimized static assets.
- Pre-rendered HTML files.
Step 2: Preview the Build Locally (Optional)
You can preview your build before deploying using:
1
2
npm install -g serve
serve -s dist
π Opens a local server for testing your production build.
2. Deploying to Netlify
Step 1: Install Netlify CLI (Optional)
If you want to deploy directly from your terminal, install Netlify CLI:
1
npm install -g netlify-cli
Step 2: Deploy Using Netlify Web Interface
- Go to Netlify.
- Click βNew site from Gitβ.
- Connect your GitHub/Bitbucket/GitLab repository.
- Select the repository containing your Vue project.
- In Build Settings, set:
- Build Command:
npm run build
- Publish Directory:
dist
- Build Command:
- Click βDeploy Siteβ π
Step 3: Deploy Using Netlify CLI (Optional)
1
netlify deploy --prod
π Deploys the dist/
folder directly from your terminal.
3. Deploying to Vercel
Vercel is another great hosting platform for Vue apps.
Step 1: Install Vercel CLI
1
npm install -g vercel
Step 2: Deploy Your App
Run the following command inside your Vue project:
1
vercel
π Follow the prompts to set up deployment.
Step 3: Configure the Build Settings
- Build Command:
npm run build
- Output Directory:
dist
π After deployment, Vercel provides a live URL for your project.
4. Deploying to GitHub Pages
Step 1: Install GitHub Pages Package
1
npm install gh-pages --save-dev
Step 2: Update vite.config.js
Modify your vite.config.js
to set the base path:
1
2
3
4
export default defineConfig({
base: "/your-repo-name/",
plugins: [vue()],
});
Step 3: Add Deployment Script
Edit package.json
:
1
2
3
4
"scripts": {
"build": "vite build",
"deploy": "gh-pages -d dist"
}
Step 4: Build & Deploy
Run:
1
2
npm run build
npm run deploy
π Your app will be live on GitHub Pages at:
1
https://your-username.github.io/your-repo-name/
Conclusion
- Netlify & Vercel are great for automatic deployments with Git.
- GitHub Pages is a good option for hosting static Vue apps.
With these deployment methods, your Vue app will be live and accessible to users worldwide! π