Vue 3 Basics
Learn the fundamentals of Vue 3, the progressive JavaScript framework for building user interfaces.
What is Vue 3?
Vue 3 is the latest major version of Vue.js, featuring:
- Composition API: More flexible component logic
- Better Performance: Smaller bundle size and faster rendering
- TypeScript Support: First-class TypeScript integration
- Multiple Root Elements: Fragments support
Installation
CDN
html
<script src="https://unpkg.com/vue@next"></script>
npm
bash
npm install vue@next
Vite (Recommended)
bash
npm create vue@latest my-project
cd my-project
npm install
npm run dev
Your First Vue App
html
<!DOCTYPE html>
<html>
<head>
<title>Vue 3 App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
<button @click="count++">Count: {{ count }}</button>
</div>
<script>
const { createApp } = Vue
createApp({
data() {
return {
message: 'Hello Vue 3!',
count: 0
}
}
}).mount('#app')
</script>
</body>
</html>
Core Concepts
Reactive Data
js
import { createApp } from 'vue'
createApp({
data() {
return {
message: 'Hello World',
count: 0,
user: {
name: 'John',
age: 30
}
}
}
}).mount('#app')
Template Syntax
html
<!-- Text Interpolation -->
<span>Message: {{ msg }}</span>
<!-- Raw HTML -->
<span v-html="rawHtml"></span>
<!-- Attribute Binding -->
<div v-bind:id="dynamicId"></div>
<div :id="dynamicId"></div>
<!-- Event Handling -->
<button v-on:click="doSomething"></button>
<button @click="doSomething"></button>
Directives
html
<!-- Conditional Rendering -->
<p v-if="seen">Now you see me</p>
<p v-else>Now you don't</p>
<!-- List Rendering -->
<ul>
<li v-for="item in items" :key="item.id">
{{ item.text }}
</li>
</ul>
<!-- Two-way Binding -->
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
Composition API
Basic Setup
js
import { ref, reactive, computed, onMounted } from 'vue'
export default {
setup() {
// Reactive state
const count = ref(0)
const user = reactive({
name: 'John',
age: 30
})
// Computed property
const doubleCount = computed(() => count.value * 2)
// Methods
const increment = () => {
count.value++
}
// Lifecycle
onMounted(() => {
console.log('Component mounted')
})
return {
count,
user,
doubleCount,
increment
}
}
}
Script Setup (Recommended)
vue
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
const count = ref(0)
const user = reactive({
name: 'John',
age: 30
})
const doubleCount = computed(() => count.value * 2)
const increment = () => {
count.value++
}
onMounted(() => {
console.log('Component mounted')
})
</script>
<template>
<div>
<p>Count: {{ count }}</p>
<p>Double: {{ doubleCount }}</p>
<button @click="increment">Increment</button>
</div>
</template>
Components
Single File Components
vue
<!-- HelloWorld.vue -->
<script setup>
import { ref } from 'vue'
const props = defineProps({
msg: String
})
const count = ref(0)
</script>
<template>
<h1>{{ msg }}</h1>
<div class="card">
<button type="button" @click="count++">
count is {{ count }}
</button>
</div>
</template>
<style scoped>
.card {
padding: 2em;
}
</style>
Component Communication
vue
<!-- Parent.vue -->
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
const message = ref('Hello from parent')
const handleChildEvent = (data) => {
console.log('Received from child:', data)
}
</script>
<template>
<Child
:message="message"
@custom-event="handleChildEvent"
/>
</template>
vue
<!-- Child.vue -->
<script setup>
const props = defineProps({
message: String
})
const emit = defineEmits(['custom-event'])
const sendToParent = () => {
emit('custom-event', 'Hello from child')
}
</script>
<template>
<div>
<p>{{ message }}</p>
<button @click="sendToParent">Send to Parent</button>
</div>
</template>
Best Practices
1. Use Composition API
- More flexible and reusable
- Better TypeScript support
- Easier to test
2. Prefer <script setup>
- Less boilerplate
- Better performance
- More intuitive
3. Use Reactive References Wisely
js
// For primitives
const count = ref(0)
// For objects
const user = reactive({
name: 'John',
age: 30
})
4. Component Naming
js
// PascalCase for components
import UserProfile from './UserProfile.vue'
// kebab-case in templates
<user-profile />
Next Steps
- Vue Router - Client-side routing
- State Management - Pinia for state management
- Vue with TypeScript - Type-safe development