Vue.js
Vue 3 cheat sheet covering Composition API, reactivity, components, directives, lifecycle hooks, and Pinia state management examples.
Sign in to mark items as known and track your progress.
Sign inGetting Started
Vue 3 setup and basics
Creating a Vue 3 App
Different ways to create Vue 3 applications
// CDN (Vue 3)
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<div id="app">{{ message }}</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return { message: 'Hello Vue!' }
}
}).mount('#app');
</script>
// Vite (Recommended for Vue 3)
npm create vue@latest my-app
cd my-app
npm install
npm run devVue 3 Composition API Setup
Script setup syntax (Vue 3 recommended way)
<template>
<div>{{ message }}</div>
<button @click="increment">{{ count }}</button>
</template>
<script setup>
import { ref, computed } from 'vue'
const message = ref('Hello')
const count = ref(0)
const doubled = computed(() => count.value * 2)
function increment() {
count.value++
}
</script>Directives
Vue built-in directives
Conditional Rendering
v-if, v-else, v-show directives
<!-- v-if/v-else (Vue 2 & 3) -->
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>Not A or B</div>
<!-- v-show (Vue 2 & 3) -->
<div v-show="isVisible">Always in DOM</div>
<!-- Template v-if (Vue 2 & 3) -->
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph</p>
</template>List Rendering
v-for directive for rendering lists
<!-- Array iteration (Vue 2 & 3) -->
<li v-for="item in items" :key="item.id">
{{ item.text }}
</li>
<!-- With index -->
<li v-for="(item, index) in items" :key="item.id">
{{ index }}: {{ item.text }}
</li>
<!-- Object iteration -->
<div v-for="(value, key) in object" :key="key">
{{ key }}: {{ value }}
</div>Event Handling & Input Binding
v-on (@) and v-model directives
<!-- Event handling (Vue 2 & 3) -->
<button @click="handleClick">Click</button>
<button @click="count++">Count: {{ count }}</button>
<!-- v-model (Vue 2 & 3) -->
<input v-model="message" />
<textarea v-model="text"></textarea>
<select v-model="selected">
<option>A</option>
<option>B</option>
</select>
<!-- Modifiers -->
<input v-model.trim="text" />
<input v-model.number="age" />
<form @submit.prevent="onSubmit">Attribute Binding
v-bind (:) directive and dynamic attributes
<!-- v-bind (Vue 2 & 3) -->
<img :src="imageSrc" :alt="imageAlt" />
<div :class="{ active: isActive }"></div>
<div :style="{ color: textColor }"></div>
<!-- Dynamic attributes (Vue 2 & 3) -->
<div :[attributeName]="value"></div>
<!-- Multiple bindings -->
<div v-bind="objectOfAttrs"></div>Computed Properties & Watchers
Reactive computations and side effects
Computed Properties
Cached reactive computations
<!-- Vue 3 Composition API -->
<script setup>
import { ref, computed } from 'vue'
const price = ref(100)
const quantity = ref(2)
const total = computed(() => price.value * quantity.value)
const formattedTotal = computed(() => `$${total.value}`)
</script>
<!-- Vue 2/3 Options API -->
<script>
export default {
data() {
return { price: 100, quantity: 2 }
},
computed: {
total() {
return this.price * this.quantity
}
}
}
</script>Watchers
Reacting to data changes with side effects
<!-- Vue 3 Composition API -->
<script setup>
import { ref, watch, watchEffect } from 'vue'
const count = ref(0)
// Watch single ref
watch(count, (newVal, oldVal) => {
console.log(`Count changed: ${oldVal} -> ${newVal}`)
})
// watchEffect runs immediately
watchEffect(() => {
console.log(`Count is: ${count.value}`)
})
</script>Refs & Reactive State
Vue 3 reactivity system
Refs and Reactive
Creating reactive state in Vue 3
<!-- Vue 3 Composition API -->
<script setup>
import { ref, reactive, toRefs, toRef } from 'vue'
// ref for primitives
const count = ref(0)
const message = ref('Hello')
// reactive for objects
const state = reactive({
user: { name: 'John' },
items: []
})
// Accessing/modifying
count.value++
state.user.name = 'Jane'
</script>Component Communication
Props, events, and provide/inject
Props
Passing data to child components
<!-- Vue 3 Script Setup -->
<script setup>
// Define props
const props = defineProps({
title: String,
count: {
type: Number,
default: 0,
required: true,
validator: (value) => value >= 0
}
})
// Use props
console.log(props.title)
</script>Custom Events
Child to parent communication
<!-- Vue 3 Child Component -->
<script setup>
const emit = defineEmits(['update', 'delete'])
function handleClick() {
emit('update', { id: 1, name: 'Updated' })
}
</script>
<!-- Parent listens -->
<ChildComponent
@update="handleUpdate"
@delete="handleDelete"
/>Provide/Inject
Dependency injection for deeply nested components
<!-- Vue 3 Provider -->
<script setup>
import { provide, ref } from 'vue'
const user = ref({ name: 'John' })
provide('user', user)
provide('theme', 'dark')
</script>
<!-- Vue 3 Consumer -->
<script setup>
import { inject } from 'vue'
const user = inject('user')
const theme = inject('theme', 'light') // with default
</script>Forms & v-model
Form handling and two-way binding
Form Inputs
v-model with different input types
<!-- Text inputs -->
<input v-model="message" />
<textarea v-model="text"></textarea>
<!-- Checkboxes -->
<input type="checkbox" v-model="checked" />
<input type="checkbox" v-model="checkedNames" value="John" />
<!-- Radio -->
<input type="radio" v-model="picked" value="One" />
<!-- Select -->
<select v-model="selected">
<option>A</option>
<option>B</option>
</select>Form Validation
Implementing form validation
<template>
<form @submit.prevent="validateAndSubmit">
<div>
<input
v-model="form.email"
@blur="validateEmail"
:class="{ error: errors.email }"
/>
<span v-if="errors.email">{{ errors.email }}</span>
</div>
<button :disabled="!isValid">Submit</button>
</form>
</template>
<script setup>
import { reactive, computed } from 'vue'
const form = reactive({
email: '',
password: ''
})
const errors = reactive({
email: '',
password: ''
})
const isValid = computed(() =>
!errors.email && !errors.password &&
form.email && form.password
)
function validateEmail() {
if (!form.email) {
errors.email = 'Email is required'
} else if (!/\S+@\S+\.\S+/.test(form.email)) {
errors.email = 'Email is invalid'
} else {
errors.email = ''
}
}
</script>Vue Router
Client-side routing in Vue
Router Setup
Setting up Vue Router
// router/index.js (Vue 3)
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/user/:id', component: User }
]
const router = createRouter({
history: createWebHistory(),
routes
})
// main.js
app.use(router)Navigation
Navigating between routes
<!-- Template navigation -->
<router-link to="/">Home</router-link>
<router-link :to="{ name: 'user', params: { id: 123 }}">
User
</router-link>
<!-- Programmatic navigation -->
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
router.push('/about')
router.push({ name: 'user', params: { id: 123 }})
</script>State Management (Pinia)
Global state management with Pinia (Vue 3)
Pinia Store
Creating and using Pinia stores
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
doubleCount: (state) => state.count * 2
},
actions: {
increment() {
this.count++
}
}
})
// Using in component
<script setup>
const counter = useCounterStore()
counter.increment()
</script>Lifecycle Hooks
Component lifecycle management
Vue 3 Lifecycle
Composition API lifecycle hooks
<script setup>
import {
onMounted,
onUpdated,
onUnmounted,
onBeforeMount,
onBeforeUpdate,
onBeforeUnmount
} from 'vue'
onMounted(() => {
console.log('Component mounted')
})
onUnmounted(() => {
console.log('Component unmounted')
})
</script>Advanced Features
Vue 3 advanced features
Slots
Content distribution with slots
<!-- Parent -->
<Card>
<template #header>
<h1>Title</h1>
</template>
Default slot content
<template #footer>
<p>Footer</p>
</template>
</Card>
<!-- Child (Card.vue) -->
<template>
<div class="card">
<header><slot name="header"></slot></header>
<main><slot></slot></main>
<footer><slot name="footer"></slot></footer>
</div>
</template>Teleport & Suspense
Vue 3 Teleport and Suspense features
<!-- Teleport -->
<Teleport to="body">
<div class="modal">
Modal content
</div>
</Teleport>
<!-- Suspense -->
<Suspense>
<AsyncComponent />
<template #fallback>
<div>Loading...</div>
</template>
</Suspense>Composables
Reusable composition functions
// composables/useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
return { x, y }
}
// Using composable
<script setup>
import { useMouse } from './composables/useMouse'
const { x, y } = useMouse()
</script>Transitions & Animations
Adding transitions and animations
Transition Component
Single element/component transitions
<!-- Basic transition -->
<Transition name="fade">
<p v-if="show">Hello</p>
</Transition>
<!-- CSS -->
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>