What is Vue.js?

Vue.js (commonly referred to as Vue) is a progressive JavaScript framework for building user interfaces and single-page applications. Unlike other 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 combines the best aspects of other frameworks like React and Angular, offering reactivity and component-based architecture with a gentler learning curve and more flexibility in integration.

Why Use Vue?

Progressive Framework

Vue can be adopted incrementally, from enhancing static HTML to powering sophisticated single-page applications.

Reactive Data Binding

Vue provides reactive and composable data binding, automatically updating the DOM when the underlying data changes.

Component System

Vue’s component-based architecture promotes reusable, maintainable code organization.

Gentle Learning Curve

Vue is known for being approachable for beginners while offering advanced features for experienced developers.

Versatile Integration

Vue can be integrated into existing projects or used to build new applications from scratch.

Comprehensive Tooling

Vue offers official tools for development, state management, routing, and more.

Getting Started with Vue

Setting Up a Vue Project

The easiest way to start a new Vue project is using the Vue CLI or the newer create-vue utility, which is based on Vite:
# Using Vue CLI
npm install -g @vue/cli
vue create my-vue-app

# Or using create-vue (recommended for Vue 3)
npm init vue@latest

# Navigate to the project directory
cd my-vue-app

# Install dependencies
npm install

# Start the development server
npm run dev

Vue Project Structure

A typical Vue project created with the Vue CLI or create-vue has the following structure:
my-vue-app/
├── node_modules/       # Dependencies
├── public/             # Static assets that won't be processed by build tools
│   └── index.html      # HTML template
├── src/                # Application source code
│   ├── assets/         # Assets that will be processed by build tools
│   ├── components/     # Vue components
│   ├── views/          # Page components (for router)
│   ├── App.vue         # Root component
│   └── main.js         # Entry point
├── package.json        # Project metadata and dependencies
└── vite.config.js      # Build configuration (or vue.config.js for Vue CLI)

Core Concepts

Vue Components

Components are the building blocks of Vue applications. A Vue component consists of three parts: template (HTML), script (JavaScript), and style (CSS).
<template>
  <div class="greeting">
    <h1>{{ message }}</h1>
    <button @click="changeMessage">Change Message</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello Vue!'
    }
  },
  methods: {
    changeMessage() {
      this.message = 'Message changed!'
    }
  }
}
</script>

<style scoped>
.greeting {
  text-align: center;
  margin-top: 2rem;
}
</style>

Vue 3 Composition API

Vue 3 introduced the Composition API, which provides a more flexible way to organize component logic:
<template>
  <div class="greeting">
    <h1>{{ message }}</h1>
    <button @click="changeMessage">Change Message</button>
  </div>
</template>

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

const message = ref('Hello Vue!')

function changeMessage() {
  message.value = 'Message changed!'
}
</script>

<style scoped>
.greeting {
  text-align: center;
  margin-top: 2rem;
}
</style>
The <script setup> syntax is a compile-time syntactic sugar for using the Composition API in Single-File Components. It’s more concise and performs better than the Options API in most cases.

Reactive Data

Vue’s reactivity system automatically updates the DOM when the underlying data changes:
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

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

const count = ref(0)

function increment() {
  count.value++
}
</script>

Directives

Vue provides built-in directives to apply special reactive behavior to the DOM:
<template>
  <div>
    <!-- Conditional rendering -->
    <p v-if="showMessage">This message is visible</p>
    <p v-else>Alternative message</p>
    
    <!-- List rendering -->
    <ul>
      <li v-for="(item, index) in items" :key="index">{{ item }}</li>
    </ul>
    
    <!-- Event handling -->
    <button v-on:click="handleClick">Click me</button>
    <!-- Shorthand for v-on -->
    <button @click="handleClick">Click me</button>
    
    <!-- Two-way binding -->
    <input v-model="inputText">
    <p>You typed: {{ inputText }}</p>
    
    <!-- Binding attributes -->
    <img v-bind:src="imageUrl" alt="Dynamic image">
    <!-- Shorthand for v-bind -->
    <img :src="imageUrl" alt="Dynamic image">
  </div>
</template>

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

const showMessage = ref(true)
const items = ref(['Apple', 'Banana', 'Cherry'])
const inputText = ref('')
const imageUrl = ref('https://example.com/image.jpg')

function handleClick() {
  showMessage.value = !showMessage.value
}
</script>

State Management

Pinia is the official state management library for Vue 3:
npm install pinia
Setting up Pinia:
// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')
Creating a store:
// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    name: 'Counter'
  }),
  getters: {
    doubleCount: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++
    }
  }
})
Using the store in a component:
<template>
  <div>
    <p>Count: {{ counter.count }}</p>
    <p>Double count: {{ counter.doubleCount }}</p>
    <button @click="counter.increment">Increment</button>
  </div>
</template>

<script setup>
import { useCounterStore } from '../stores/counter'

const counter = useCounterStore()
</script>

Vuex (Vue 2 and early Vue 3)

Vuex is the original state management pattern and library for Vue:
npm install vuex
Setting up Vuex:
// store/index.js
import { createStore } from 'vuex'

export default createStore({
  state: {
    count: 0
  },
  getters: {
    doubleCount: state => state.count * 2
  },
  mutations: {
    increment(state) {
      state.count++
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment')
      }, 1000)
    }
  }
})

Routing

Vue Router is the official router for Vue.js:
npm install vue-router
Setting up Vue Router:
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: About
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router
Using the router in your app:
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router)
app.mount('#app')
Router components in your template:
<template>
  <div>
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>
    
    <!-- Route components are rendered here -->
    <router-view />
  </div>
</template>

Composition API vs Options API

Vue 3 supports two styles of writing components: the Options API (traditional) and the Composition API (new in Vue 3).

Options API

Organizes code by option types (data, methods, computed, etc.). Familiar to Vue 2 developers and often easier for beginners.

Composition API

Organizes code by logical concerns. More flexible, better TypeScript integration, and better performance for complex components.

Options API Example

<script>
export default {
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    }
  },
  computed: {
    fullName() {
      return `${this.firstName} ${this.lastName}`
    }
  },
  methods: {
    updateName(newFirstName) {
      this.firstName = newFirstName
    }
  }
}
</script>

Composition API Example

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

const firstName = ref('John')
const lastName = ref('Doe')

const fullName = computed(() => {
  return `${firstName.value} ${lastName.value}`
})

function updateName(newFirstName) {
  firstName.value = newFirstName
}
</script>

Vue Ecosystem

Vue Router

Official router for Vue.js applications

Pinia/Vuex

State management for Vue applications

Nuxt.js

Framework for creating Vue.js applications with server-side rendering, static site generation, and more

Vite

Next-generation frontend tooling with instant server start and hot module replacement

Vue Test Utils

Official testing utility library for Vue.js

Vue DevTools

Browser extension for debugging Vue applications

Best Practices

Component Organization

  • Keep components small and focused on a single responsibility
  • Use props for passing data down to child components
  • Use events for communication from child to parent components
  • Use slots for flexible component composition

Performance Optimization

  • Use v-show instead of v-if for elements that toggle frequently
  • Use key with v-for to help Vue optimize rendering
  • Avoid expensive operations in computed properties
  • Use async components for code-splitting
// Async component registration
const AsyncComponent = defineAsyncComponent(() =>
  import('./components/AsyncComponent.vue')
)

TypeScript Integration

Vue 3 has excellent TypeScript support, especially with the Composition API:
<script setup lang="ts">
import { ref, computed } from 'vue'

interface User {
  id: number
  name: string
  email: string
}

const user = ref<User | null>(null)

const userName = computed(() => {
  return user.value ? user.value.name : 'Guest'
})

async function fetchUser(id: number): Promise<void> {
  const response = await fetch(`/api/users/${id}`)
  user.value = await response.json()
}
</script>

Conclusion

Vue.js offers a progressive approach to building user interfaces, making it suitable for projects of all sizes. Its gentle learning curve, combined with powerful features, has made it one of the most popular frontend frameworks. Whether you’re enhancing static HTML pages or building complex single-page applications, Vue provides the tools and patterns to make development efficient and enjoyable.
Vue 3 is the current stable version and is recommended for all new projects. If you’re working with Vue 2, consider migrating to Vue 3 to take advantage of its improved performance, Composition API, and better TypeScript support.