7.1: Vue.js Introduction & Setup

Discover Vue.js, a progressive JavaScript framework for building modern user interfaces. Learn the benefits of using Vue, set up your development environment, and create your first Vue application.

1. Why Do We Need Frontend Frameworks?

The Problem with Vanilla JavaScript

In the previous phases, you built interactive web applications using vanilla JavaScript. While powerful, this approach has limitations:

Example: Todo List in Vanilla JavaScript

// State management is manual and error-prone
let todos = [];

// DOM manipulation is verbose and repetitive
function addTodo(text) {
  todos.push({ id: Date.now(), text, completed: false });
  renderTodos(); // Must manually re-render
}

function renderTodos() {
  const list = document.getElementById('todo-list');
  list.innerHTML = ''; // Clear everything

  todos.forEach(todo => {
    const li = document.createElement('li');
    li.textContent = todo.text;
    li.addEventListener('click', () => toggleTodo(todo.id));
    list.appendChild(li);
  });
}

Problems:

  • Manual DOM manipulation is tedious and error-prone
  • State and UI can get out of sync
  • No built-in reactivity (must manually trigger updates)
  • Event listeners can cause memory leaks if not cleaned up
  • Code becomes difficult to maintain as complexity grows
  • No component reusability

How Frameworks Solve These Problems

Modern frameworks like Vue.js provide:

  1. Reactivity: UI automatically updates when data changes
  2. Component Architecture: Reusable, self-contained UI pieces
  3. Declarative Rendering: Describe what UI should look like, not how to build it
  4. Developer Tools: Better debugging and development experience
  5. Performance Optimizations: Virtual DOM and efficient updates
  6. Ecosystem: Routing, state management, build tools all integrated

Same Todo List in Vue 3:

<script setup>
import { ref } from 'vue'

const todos = ref([])
const newTodo = ref('')

function addTodo() {
  todos.value.push({
    id: Date.now(),
    text: newTodo.value,
    completed: false
  })
  newTodo.value = ''
}

function toggleTodo(id) {
  const todo = todos.value.find(t => t.id === id)
  if (todo) todo.completed = !todo.completed
}
</script>

<template>
  <div>
    <input v-model="newTodo" @keyup.enter="addTodo">
    <button @click="addTodo">Add</button>

    <ul>
      <li
        v-for="todo in todos"
        :key="todo.id"
        @click="toggleTodo(todo.id)"
        :class="{ completed: todo.completed }"
      >
        {{ todo.text }}
      </li>
    </ul>
  </div>
</template>

<style scoped>
.completed {
  text-decoration: line-through;
  opacity: 0.6;
}
</style>

Benefits:

  • Much less code, more readable
  • Automatic reactivity (no manual re-rendering)
  • Declarative template syntax
  • Component encapsulation (styles, logic, template together)
  • Event handlers automatically cleaned up

2. Introduction to Vue.js

What is Vue.js?

Vue.js (pronounced "view") is a progressive JavaScript framework for building user interfaces.

Key Characteristics:

  • Progressive: Can be adopted incrementally (use as little or as much as needed)
  • Approachable: Easy to learn if you know HTML, CSS, and JavaScript
  • Versatile: Can scale from simple widgets to full-scale SPAs
  • Performant: Virtual DOM and optimized reactivity system

Vue.js History

  • Created by Evan You in 2014
  • Vue 3 released in 2020 with major improvements
  • Extremely popular in China (Alibaba, Xiaomi, Tencent)
  • Growing worldwide adoption

Vue 3 vs Vue 2

Vue 3 Improvements:

  • Composition API: Better code organization (vs Options API)
  • Better TypeScript support
  • Smaller bundle size (tree-shakable)
  • Faster performance
  • Better IDE support

This course uses Vue 3 with Composition API - the modern, recommended approach.

Vue vs Other Frameworks

FeatureVue 3ReactAngular
Learning CurveEasyModerateSteep
SizeSmall (~34KB)Small (~40KB)Large (~150KB)
PerformanceExcellentExcellentGood
Template SyntaxHTML-basedJSXHTML-based
State ManagementPiniaRedux/ContextRxJS/Services
TypeScriptOptionalOptionalRequired
Popularity in ChinaVery HighHighModerate

When to choose Vue:

  • You want an easy learning curve
  • You prefer HTML-based templates
  • You're building apps for Chinese market
  • You want a complete, integrated solution
  • You value official routing and state management

3. Setting Up Vue 3

Method 1: CDN (Quick Start - Good for Learning)

The fastest way to try Vue is via CDN:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <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>

Pros:

  • No build tools needed
  • Great for learning and prototyping
  • Works in any browser

Cons:

  • No Single File Components (.vue files)
  • No hot module replacement
  • Not suitable for production apps

Vite is the official Vue build tool - fast, modern, and powerful.

Create a new Vue 3 project:

# Create project
npm create vue@latest

# Follow prompts:
# ✔ Project name: my-vue-app
# ✔ Add TypeScript? No
# ✔ Add JSX Support? No
# ✔ Add Vue Router? Yes (for multi-page apps)
# ✔ Add Pinia? Yes (for state management)
# ✔ Add Vitest? No (testing - skip for now)
# ✔ Add ESLint? Yes (code quality)

# Navigate to project
cd my-vue-app

# Install dependencies
npm install

# Start development server
npm run dev

Project structure:

my-vue-app/
├── node_modules/        # Dependencies
├── public/              # Static assets
│   └── favicon.ico
├── src/
│   ├── assets/         # Images, styles
│   ├── components/     # Vue components
│   ├── router/         # Vue Router config
│   ├── stores/         # Pinia stores
│   ├── views/          # Page components
│   ├── App.vue         # Root component
│   └── main.js         # Entry point
├── index.html          # HTML template
├── package.json        # Project config
└── vite.config.js      # Vite config

Key files explained:

main.js - Application entry point:

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(createPinia())
app.use(router)

app.mount('#app')

App.vue - Root component:

<script setup>
import { RouterLink, RouterView } from 'vue-router'
</script>

<template>
  <header>
    <nav>
      <RouterLink to="/">Home</RouterLink>
      <RouterLink to="/about">About</RouterLink>
    </nav>
  </header>

  <main>
    <RouterView />
  </main>
</template>

<style scoped>
/* Component-specific styles */
</style>

Method 3: Single File in Existing Project

You can add Vue to an existing website:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My App</title>
  <script type="importmap">
    {
      "imports": {
        "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
      }
    }
  </script>
</head>
<body>
  <div id="app"></div>
  <script type="module" src="/main.js"></script>
</body>
</html>
// main.js
import { createApp, ref } from 'vue'

createApp({
  setup() {
    const message = ref('Hello!')
    return { message }
  },
  template: `<h1>{{ message }}</h1>`
}).mount('#app')

4. Vue DevTools

Installing Vue DevTools

Vue DevTools is essential for debugging Vue applications.

Browser Extensions:

Using Vue DevTools

Features:

  1. Component Tree: Inspect component hierarchy
  2. Component State: View and edit component data
  3. Events: Track emitted events
  4. Routing: See current route and navigation history
  5. Pinia Stores: Inspect global state
  6. Performance: Analyze component render times

How to open:

  • Open browser DevTools (F12)
  • Look for "Vue" tab
  • If using Vite dev server, DevTools should automatically detect Vue

Common uses:

  • Check if data is updating correctly
  • Inspect prop values passed to components
  • Debug event emissions
  • Monitor state changes
  • Identify performance bottlenecks

5. Your First Vue Application

Understanding the Composition API

Vue 3's Composition API uses a <script setup> syntax for cleaner code:

<script setup>
// Imports
import { ref, computed } from 'vue'

// Reactive state
const count = ref(0)
const message = ref('Hello')

// Computed properties
const doubleCount = computed(() => count.value * 2)

// Methods
function increment() {
  count.value++
}

// Everything is automatically available in template
</script>

<template>
  <div>
    <p>{{ message }}</p>
    <p>Count: {{ count }}</p>
    <p>Double: {{ doubleCount }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

Key concepts:

  • ref() creates reactive data
  • Access ref values with .value in script
  • No .value needed in template
  • computed() for derived state
  • All declared variables/functions auto-exposed to template

Building a Counter App

Let's build a complete counter with multiple features:

<script setup>
import { ref, computed } from 'vue'

// State
const count = ref(0)
const step = ref(1)

// Computed properties
const isEven = computed(() => count.value % 2 === 0)
const parity = computed(() => isEven.value ? 'even' : 'odd')

// Methods
function increment() {
  count.value += step.value
}

function decrement() {
  count.value -= step.value
}

function reset() {
  count.value = 0
}
</script>

<template>
  <div class="counter">
    <h1>Counter App</h1>

    <div class="display">
      <h2>{{ count }}</h2>
      <p>This number is {{ parity }}</p>
    </div>

    <div class="controls">
      <label>
        Step:
        <input
          v-model.number="step"
          type="number"
          min="1"
        >
      </label>

      <div class="buttons">
        <button @click="decrement">- {{ step }}</button>
        <button @click="reset">Reset</button>
        <button @click="increment">+ {{ step }}</button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.counter {
  max-width: 400px;
  margin: 2rem auto;
  padding: 2rem;
  border: 2px solid #42b983;
  border-radius: 8px;
  text-align: center;
}

.display {
  margin: 2rem 0;
}

.display h2 {
  font-size: 4rem;
  margin: 0;
  color: #42b983;
}

.display p {
  color: #666;
  font-style: italic;
}

.controls {
  margin-top: 2rem;
}

.controls label {
  display: block;
  margin-bottom: 1rem;
}

.controls input {
  width: 60px;
  margin-left: 0.5rem;
  padding: 0.25rem;
}

.buttons {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
}

button {
  padding: 0.5rem 1rem;
  font-size: 1rem;
  border: 2px solid #42b983;
  background: white;
  color: #42b983;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

button:hover {
  background: #42b983;
  color: white;
}
</style>

What's happening:

  • ref() creates reactive state (count, step)
  • computed() derives values from state (isEven, parity)
  • v-model.number binds input to state (two-way binding)
  • @click attaches event handlers
  • {{ }} displays reactive data
  • scoped styles only apply to this component

6. Vue Reactivity System

How Reactivity Works

Vue 3 uses JavaScript Proxies to track dependencies and trigger updates:

import { ref, watchEffect } from 'vue'

const count = ref(0)

// This function re-runs whenever count changes
watchEffect(() => {
  console.log(`Count is: ${count.value}`)
})

count.value++ // Console logs: "Count is: 1"
count.value++ // Console logs: "Count is: 2"

Under the hood:

  1. ref() wraps value in a reactive Proxy
  2. When you read .value, Vue tracks the dependency
  3. When you write .value, Vue triggers updates
  4. Template automatically re-renders

ref() vs reactive()

Two ways to create reactive state:

ref() - For primitives and objects:

import { ref } from 'vue'

const count = ref(0)
const user = ref({ name: 'Alice' })

// Access with .value
count.value++
user.value.name = 'Bob'

reactive() - Only for objects:

import { reactive } from 'vue'

const user = reactive({
  name: 'Alice',
  age: 25
})

// No .value needed
user.name = 'Bob'
user.age++

When to use which:

  • Use ref() for: primitives (numbers, strings, booleans)
  • Use ref() for: single objects you might reassign
  • Use reactive() for: complex objects you'll mutate

Best practice: Stick with ref() for consistency until you need reactive().


7. Practical Exercises

Exercise 5.1.1: CDN Setup

Create an HTML file with Vue 3 via CDN:

  1. Include Vue 3 from CDN
  2. Create an app that displays your name
  3. Add a button that changes the name
  4. Add an input that updates the name in real-time

Exercise 5.1.2: Vite Project

Set up a Vue 3 project with Vite:

  1. Create new project: npm create vue@latest
  2. Install dependencies
  3. Start dev server
  4. Modify App.vue to display a custom message
  5. Open Vue DevTools and inspect the component

Exercise 5.1.3: Calculator

Build a simple calculator:

  1. Two number inputs (use v-model.number)
  2. Buttons for +, -, ×, ÷
  3. Display result using computed property
  4. Add reset button
  5. Style it nicely

Exercise 5.1.4: Unit Converter

Create a temperature converter:

  1. Input for Celsius
  2. Automatically show Fahrenheit (computed)
  3. Input for Fahrenheit
  4. Automatically show Celsius (computed)
  5. Both inputs should update each other
  6. Formula: F = C × 9/5 + 32

8. Knowledge Check

Question 1: What problem does Vue.js solve compared to vanilla JavaScript?

Show answer Vue provides automatic reactivity (UI updates when data changes), component architecture for reusability, declarative templates, and built-in optimizations. Vanilla JS requires manual DOM manipulation and state synchronization.

Question 2: What is the difference between ref() and reactive()?

Show answer `ref()` works with primitives and objects, requires `.value` access. `reactive()` only works with objects, no `.value` needed. `ref()` is more versatile and recommended for most cases.

Question 3: What does <script setup> do?

Show answer ` When should you use Vue DevTools?
Show answer Use Vue DevTools to inspect component state, track events, debug reactivity issues, monitor performance, and inspect routing/store state.

Question 5: What is the Virtual DOM?

Show answer The Virtual DOM is a lightweight JavaScript representation of the actual DOM. Vue compares changes in the virtual DOM and only updates the real DOM where needed, improving performance.

9. Common Mistakes to Avoid

Mistake 1: Forgetting .value in script

// Wrong
const count = ref(0)
count++ // Won't work!

// Correct
const count = ref(0)
count.value++ // Works!

Mistake 2: Using .value in template

<template>
  <!-- Wrong -->
  <p>{{ count.value }}</p>

  <!-- Correct -->
  <p>{{ count }}</p>
</template>

Mistake 3: Mutating props directly

// Wrong - don't modify props
const props = defineProps(['count'])
props.count++ // Error!

// Correct - emit event to parent
const emit = defineEmits(['update'])
emit('update', props.count + 1)

Mistake 4: Not using computed for derived state

// Less efficient - runs on every render
const doubleCount = count.value * 2

// Better - only recalculates when count changes
const doubleCount = computed(() => count.value * 2)

10. Key Takeaways

  • Vue.js is a progressive framework for building user interfaces
  • Reactivity means UI automatically updates when data changes
  • Composition API (<script setup>) is the modern Vue 3 approach
  • ref() creates reactive state (use .value in script)
  • computed() creates derived reactive values
  • Vite is the recommended build tool for Vue projects
  • Vue DevTools are essential for debugging
  • Single File Components (.vue) combine template, script, and styles
  • Vue is easier to learn than React/Angular
  • Vue is very popular in China

11. Further Resources

Official Documentation:

Interactive Learning:

Tools:


Next Steps

Great work! You now understand why frameworks exist and have set up your first Vue 3 application.

In Lesson 5.2: Template Syntax & Reactivity, you'll learn Vue's template directives, data binding, and reactivity system in depth.