Building Vue 3 Applications: Core Concepts and Project Structure

Vue 3 Framework Overview

Vue 3 is a progressive JavaScript framework designed for building user interfaces. It relies on a reactivity system that automatically updates the DOM when data changes, eliminating the need for manual DOM manipulation.

Project Initialization and Directory Structure

Prerequisites

Ensure Node.js (v18.0 LTS or higher) is installed on your system.

Scaffolding the Project

Execute the following commands in your terminal to create and launch a new project named my-vue-app:

npm create vue@latest
cd my-vue-app
npm install
npm run dev

Navigate to http://localhost:5173/ in your browser to view the default application.

Directory Architecture

my-vue-app/
├── node_modules/       # Dependencies
├── public/             # Static assets
├── src/                # Source code
│   ├── assets/         # Images and global styles
│   ├── components/     # Reusable UI components
│   ├── views/          # Route-level components
│   ├── router/         # Routing configuration
│   ├── stores/         # Global state management
│   ├── App.vue         # Root component
│   └── main.js         # Application entry point
├── index.html          # HTML entry point
└── package.        # Project metadata and dependencies

Single File Component Syntax

Vue applications are built using .vue files, which encapsulate template, logic, and styles:

<template>
  <div class="container">Application Content</div>
</template>

<script setup>
// Component logic and reactivity
</script>

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

Reactive State Management

Primitive Values with ref

Use ref for primitive data types (strings, numbers, booleans). Access or modify the value using the .value property in the script block.

<template>
  <div>
    <p>User: {{ userName }}</p>
    <p>Age: {{ userAge }}</p>
  </div>
</template>

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

const userName = ref('John Doe')
const userAge = ref(25)

userAge.value = 26
</script>

Complex Objects with reactive

Use reactive for objects and arrays. Direct property mutation is allowed without .value.

<template>
  <div>
    <p>Account: {{ accountDetails.alias }}</p>
    <p>Completion: {{ accountDetails.completionRate }}%</p>
  </div>
</template>

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

const accountDetails = reactive({
  alias: 'Developer',
  completionRate: 45
})

accountDetails.completionRate = 60
</script>

Event Handling and Data Binding

Click Events

Attach event listeners using the @ directive.

<template>
  <p>Counter: {{ counter }}</p>
  <button @click="increment">Increment</button>
</template>

<script setup>
import { ref } from 'vue'
const counter = ref(0)

const increment = () => {
  counter.value++
}
</script>

Two-Way Binding

Sync form input values with reactive state using v-model.

<template>
  <input type="text" v-model="textInput" placeholder="Enter text" />
  <p>Live output: {{ textInput }}</p>
</template>

<script setup>
import { ref } from 'vue'
const textInput = ref('')
</script>

Component Communication

Child Component Definition

Create a file at src/components/SubComponent.vue.

Parent-to-Child (Props)

Child component consuming the prop:

<!-- SubComponent.vue -->
<template>
  <div>
    <p>Received message: {{ titleMessage }}</p>
  </div>
</template>

<script setup>
defineProps({
  titleMessage: String
})
</script>

Parent component passing the prop:

<!-- App.vue -->
<template>
  <SubComponent titleMessage="Data from parent" />
</template>

<script setup>
import SubComponent from './components/SubComponent.vue'
</script>

Child-to-Parent (Emits)

Child component emitting an event:

<!-- SubComponent.vue -->
<template>
  <button @click="dispatchToParent">Send to Parent</button>
</template>

<script setup>
const emit = defineEmits(['notifyParent'])

const dispatchToParent = () => {
  emit('notifyParent', 'Operation successful')
}
</script>

Parent component listening for the event:

<!-- App.vue -->
<template>
  <SubComponent @notify-parent="processChildData" />
  <p v-if="receivedPayload">Child says: {{ receivedPayload }}</p>
</template>

<script setup>
import { ref } from 'vue'
import SubComponent from './components/SubComponent.vue'

const receivedPayload = ref('')

const processChildData = (payload) => {
  receivedPayload.value = payload
}
</script>

Component Lifecycle

Execute logic after the component is mounted using onMounted. This is commonly used for initial data fetching.

<script setup>
import { ref, onMounted } from 'vue'
const initialPayload = ref('')

onMounted(() => {
  initialPayload.value = 'Initialization complete'
  console.log('Component mounted')
})
</script>

Client-Side Routing

Installation

npm install vue-router@4

Router Configuration

Create src/router/index.js:

import { createRouter, createWebHistory } from 'vue-router'
import Dashboard from '../views/Dashboard.vue'
import Settings from '../views/Settings.vue'

const pathMappings = [
  { path: '/', redirect: '/dashboard' },
  { path: '/dashboard', component: Dashboard },
  { path: '/settings', component: Settings }
]

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

export default routerInstance

Application Mounting

Update src/main.js:

import { createApp } from 'vue'
import App from './App.vue'
import routerInstance from './router'

const application = createApp(App)
application.use(routerInstance)
application.mount('#app')

Navigation Implementation

Modify src/App.vue:

<template>
  <nav>
    <router-link to="/dashboard">Dashboard</router-link>
    <router-link to="/settings">Settings</router-link>
  </nav>
  <router-view />
</template>

Global State with Pinia

Installation

npm install pinia

Store Definition

Create src/stores/auth.js:

import { defineStore } from 'pinia'

export const useAuthStore = defineStore('auth', {
  state: () => ({
    authKey: 'default-key-xyz'
  }),
  actions: {
    updateAuthKey(newKey) {
      this.authKey = newKey
    }
  }
})

Store Consumption

<script setup>
import { useAuthStore } from './stores/auth'
const authStore = useAuthStore()

// Read state
console.log(authStore.authKey)
// Update state
authStore.updateAuthKey('updated-key-abc')
</script>

UI Integration with Element Plus

Installation

npm install element-plus

Global Registration

Update src/main.js:

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const application = createApp(App)
application.use(ElementPlus)
application.mount('#app')

Component Usage

<template>
  <el-button type="success">Submit</el-button>
  <el-input placeholder="Enter credentials"></el-input>
</template>

Tags: Vue 3 Frontend Development JavaScript Framework Single File Components Pinia

Posted on Sun, 13 Sep 2026 16:36:27 +0000 by Grisu