javascriptroom guide

Intro to Vue.js: Building your First Interactive Page

Vue.js (often called Vue) is a progressive JavaScript framework for building user interfaces. Unlike monolithic frameworks, Vue is designed to be incrementally adoptable—you can integrate it into a project as needed, or build full-scale single-page applications (SPAs) with it. Its core focus is on the **view layer**, making it easy to learn and integrate with other libraries or existing projects. What makes Vue popular? Its simplicity, reactivity system (automatically updates the DOM when data changes), and gentle learning curve. Whether you’re new to frameworks or coming from React or Angular, Vue’s intuitive syntax and clear documentation make it a great choice for building interactive web pages. In this tutorial, we’ll walk through the basics of Vue.js and build a fully functional interactive page: a dynamic todo list. By the end, you’ll understand core Vue concepts like data binding, event handling, conditional rendering, and list rendering—and how to combine them to create engaging user experiences.

Table of Contents

Prerequisites

Before diving in, ensure you have:

  • Basic knowledge of HTML, CSS, and JavaScript (ES6+ recommended).
  • A code editor (e.g., VS Code).
  • A modern web browser (Chrome, Firefox, Edge).
  • Internet connection (to load Vue via CDN and optional styling libraries).

Setting Up Vue.js

Vue.js can be set up in multiple ways. For beginners, the CDN (Content Delivery Network) approach is the simplest—no complex build tools required.

Using the Vue CDN

Add the following script tag to the <head> of your HTML file to load Vue.js:

<!-- Load Vue.js from CDN -->  
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  

This loads the latest stable version of Vue 3 (the current major release). For production, specify a version (e.g., [email protected]) to avoid unexpected updates.

Core Vue Concepts You’ll Need

Let’s break down the foundational Vue concepts we’ll use to build our interactive page.

Data Binding

Vue’s reactivity system lets you bind data to the DOM seamlessly. The most common forms are:

Text Interpolation

Use double curly braces {{ }} to display data in the template:

<div id="app">  
  <h1>{{ message }}</h1>  
</div>  

<script>  
const { createApp } = Vue;  

createApp({  
  data() {  
    return {  
      message: "Hello, Vue!"  
    }  
  }  
}).mount('#app');  
</script>  

Here, message is a reactive data property. If you update message later (e.g., via a button click), the DOM will automatically update.

Attribute Binding

Use v-bind: (or the shorthand :) to bind data to HTML attributes:

<img :src="imageUrl" :alt="imageAlt">  

In the Vue instance:

data() {  
  return {  
    imageUrl: "https://example.com/vue-logo.png",  
    imageAlt: "Vue.js Logo"  
  }  
}  

Two-Way Binding

Use v-model to sync form input values with reactive data (two-way binding):

<input v-model="username" placeholder="Enter your name">  
<p>Hello, {{ username }}!</p>  

Typing in the input updates username, and username updates the paragraph in real time.

Methods & Event Handling

Use v-on: (or shorthand @) to handle DOM events (e.g., clicks, input). Define methods in the Vue instance to respond to events.

Example: A counter that increments on button click

<div id="app">  
  <p>Count: {{ count }}</p>  
  <button @click="increment">Increment</button>  
</div>  

<script>  
createApp({  
  data() {  
    return {  
      count: 0  
    }  
  },  
  methods: {  
    increment() {  
      this.count++; // "this" refers to the Vue instance  
    }  
  }  
}).mount('#app');  
</script>  

Conditional Rendering

Use v-if/v-else/v-else-if to conditionally render elements (adds/removes from the DOM) or v-show (toggles display: none):

<div v-if="isLoggedIn">Welcome back!</div>  
<div v-else>Please log in.</div>  

<!-- Toggle visibility with v-show -->  
<p v-show="hasNotifications">You have unread messages.</p>  

List Rendering

Use v-for to loop through arrays and render lists. Always include a :key attribute for performance:

<ul>  
  <li v-for="(item, index) in items" :key="index">  
    {{ index + 1 }}. {{ item }}  
  </li>  
</ul>  

In the Vue instance:

data() {  
  return {  
    items: ["Learn Vue", "Build an app", "Deploy!"]  
  }  
}  

Building Your Interactive Page: A Todo List App

Now, let’s combine these concepts to build a todo list with the following features:

  • Add new todos via an input field.
  • Mark todos as “completed.”
  • Delete todos.
  • Show a message if no todos exist.

Step 1: Project Setup

Create a new HTML file (e.g., index.html) and set up the basic structure. Include the Vue CDN and a CSS library (we’ll use Bootstrap for simplicity):

<!DOCTYPE html>  
<html lang="en">  
<head>  
  <meta charset="UTF-8">  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">  
  <title>Vue Todo List</title>  
  <!-- Bootstrap for styling (optional but helpful) -->  
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">  
  <!-- Vue.js CDN -->  
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
</head>  
<body>  
  <div class="container mt-5" id="app">  
    <!-- Todo app content will go here -->  
  </div>  

  <script>  
    // Vue app logic will go here  
  </script>  
</body>  
</html>  

Step 2: Define the Vue Instance

Initialize the Vue app and define reactive data for todos and a new todo input:

const { createApp } = Vue;  

createApp({  
  data() {  
    return {  
      newTodo: "", // Binds to the input field via v-model  
      todos: [  
        // Sample initial todos  
        { id: 1, text: "Learn Vue basics", completed: false },  
        { id: 2, text: "Build a todo app", completed: true }  
      ]  
    };  
  }  
}).mount("#app");  

Step 3: Add Todo Functionality

Add an input field to enter new todos and a button to add them to the list. Use v-model for two-way binding and @click to trigger an addTodo method:

Template (inside #app):

<div class="card p-4">  
  <h2 class="text-center mb-4">Todo List</h2>  

  <!-- Add Todo Input -->  
  <div class="input-group mb-3">  
    <input  
      v-model="newTodo"  
      @keyup.enter="addTodo" <!-- Add on Enter key press -->  
      type="text"  
      class="form-control"  
      placeholder="Add a new todo..."  
    >  
    <button @click="addTodo" class="btn btn-primary">Add</button>  
  </div>  

  <!-- Todo List -->  
  <ul class="list-group">  
    <!-- Todo items will go here -->  
  </ul>  
</div>  

Add the addTodo method to the Vue instance:

methods: {  
  addTodo() {  
    if (this.newTodo.trim()) { // Ignore empty/whitespace todos  
      this.todos.push({  
        id: Date.now(), // Unique ID using timestamp  
        text: this.newTodo.trim(),  
        completed: false  
      });  
      this.newTodo = ""; // Clear input after adding  
    }  
  }  
}  

Step 4: Mark Todos as Complete

Use v-for to render todos and v-bind:class to style completed todos (e.g., strikethrough text). Add a checkbox to toggle completed status:

Update the <ul> in the template:

<ul class="list-group">  
  <li  
    v-for="todo in todos"  
    :key="todo.id"  
    class="list-group-item d-flex align-items-center justify-content-between"  
  >  
    <div class="d-flex align-items-center">  
      <input  
        type="checkbox"  
        v-model="todo.completed"  
        class="me-3"  
      >  
      <span :class="{ 'text-decoration-line-through text-muted': todo.completed }">  
        {{ todo.text }}  
      </span>  
    </div>  
    <!-- Delete button will go here -->  
  </li>  

  <!-- Show message if no todos -->  
  <li v-if="todos.length === 0" class="list-group-item text-center text-muted">  
    No todos yet. Add your first todo!  
  </li>  
</ul>  

Here, :class="{ 'text-decoration-line-through text-muted': todo.completed }" applies styles conditionally when todo.completed is true.

Step 5: Delete Todos

Add a delete button for each todo and a deleteTodo method to remove todos from the list:

Add the delete button to each list item:

<button @click="deleteTodo(todo.id)" class="btn btn-danger btn-sm">×</button>  

Add the deleteTodo method to the Vue instance:

methods: {  
  // ... (addTodo method)  
  deleteTodo(todoId) {  
    this.todos = this.todos.filter(todo => todo.id !== todoId);  
  }  
}  

Styling Your Interactive Page

With Bootstrap, the app already looks clean, but you can customize styles further. For example, highlight completed todos with a light gray background:

/* Add to <style> in <head> */  
.list-group-item {  
  transition: all 0.2s;  
}  

.list-group-item:hover {  
  background-color: #f8f9fa;  
}  

/* Completed todo style */  
.list-group-item .text-decoration-line-through {  
  opacity: 0.7;  
}  

Testing & Debugging with Vue DevTools

Vue DevTools is a browser extension that lets you inspect Vue components, track reactive data, and debug your app in real time.

Install Vue DevTools:

  • Chrome/Firefox: Search for “Vue DevTools” in the Chrome Web Store or Firefox Add-ons.
  • Edge: Use the Chrome extension via the Microsoft Edge Add-ons store.

Once installed, open your app in the browser and launch DevTools (F12 or Ctrl+Shift+I). You’ll see a “Vue” tab to inspect your app’s data, methods, and components.

Conclusion

You’ve built a fully interactive todo list with Vue.js! You learned:

  • How to set up Vue.js via CDN.
  • Core concepts: data binding ({{ }}, v-bind, v-model), event handling (v-on), conditional rendering (v-if), and list rendering (v-for).
  • How to combine these to build a functional app.
  • Styling with conditional classes and debugging with Vue DevTools.

Vue’s simplicity and reactivity make it a joy to build interactive UIs. Next steps: explore Vue 3’s Composition API, Vue Router for multi-page apps, or Pinia for state management!

References