| |

Vue.js 101 🟢 Cheatsheet

⏱️ Estimated read: 6 min | |

A quick-reference for Vue 3 APIs, reactivity, components, and internals. Organized for lookup, not for reading.


Component Definition

SyntaxMeaning
<script setup>Composition API, compiled to setup()
defineComponent({})Options API with TS support
export default {}Options API object
<script setup lang="ts">TypeScript + Composition API
<script setup vapor>Vapor Mode component (Vue 3.6+)

Reactivity: Core

FunctionPurpose
ref(v)Reactive wrapper, access via .value
reactive(obj)Deep reactive proxy
shallowRef(v)Only .value reactive
shallowReactive(obj)Only root props reactive
computed(fn)Cached derived value
readonly(obj)Read-only proxy
shallowReadonly(obj)Shallow read-only
markRaw(obj)Never proxy this object
toRaw(proxy)Get original object
isRef(v)Type guard for refs
isReactive(v)Check for reactive proxy
isReadonly(v)Check for readonly proxy
unref(v)Unwrap ref, otherwise return value
toRef(obj, key)Synced ref to a property
toRef(() => expr)Read-only ref from getter (3.3+)
toRefs(obj)Synced refs for all props
customRef(factory)Manual track/trigger
triggerRef(ref)Force update on a shallow ref

Reactivity: Effects

FunctionPurpose
watchEffect(fn)Run fn, track deps, re-run on change
watch(src, cb)Explicit source watching
watchPostEffect(fn)After DOM update
watchSyncEffect(fn)Synchronous
effectScope()Group effects
scope.run(fn)Run fn, capture effects
scope.stop()Stop all captured effects
onScopeDispose(fn)Cleanup on scope stop
getCurrentScope()Current active scope
stop(handle)Stop a watch

Watch Options

OptionEffect
immediate: trueRun callback on creation
deep: trueWatch nested mutations
flush: 'pre'Before DOM update (default)
flush: 'post'After DOM update
flush: 'sync'Synchronously
once: trueRun once, then stop (3.4+)
watch(source, (newVal, oldVal) => {}, {
  immediate: true,
  deep: true,
  flush: 'post',
})

Component Lifecycle

HookWhen
onBeforeMountBefore DOM mount
onMountedAfter DOM mount
onBeforeUpdateBefore re-render
onUpdatedAfter re-render
onBeforeUnmountBefore unmount
onUnmountedAfter unmount
onActivatedInside <KeepAlive> shown
onDeactivatedInside <KeepAlive> hidden
onErrorCapturedDescendant error
onRenderTrackedDev: reactive dep tracked
onRenderTriggeredDev: reactive dep triggered

Component APIs

FunctionPurpose
defineProps()Declare props
defineEmits()Declare emits
defineExpose()Expose public instance
defineModel()Two-way prop (3.4+)
defineOptions()Component options (3.3+)
defineSlots()Typed slots (3.3+)
useSlots()Access slots
useAttrs()Access fallthrough attrs
useTemplateRef()Template ref (3.5+)
useId()Unique ID (3.5+)
getCurrentInstance()Component instance (null in Vapor)
nextTick()Wait for DOM flush
useModel()Custom model logic (3.4+)

Props & Emits

// Props
const props = defineProps<{ title: string; count?: number }>()

// Props with defaults (3.5+)
const { title, count = 0 } = defineProps<{ title: string; count?: number }>()

// Emits
const emit = defineEmits<{
  change: [value: string]
  close: []
}>()

// Model
const model = defineModel<string>()

Template Syntax

DirectivePurpose
v-if / v-else-if / v-elseConditional
v-showToggle display
v-forLoop
v-on / @Event
v-bind / :Attribute/prop
v-modelTwo-way binding
v-slot / #Slot
v-htmlRaw HTML
v-textText content
v-onceRender once
v-memoMemoize list items
v-preSkip compilation

v-for Key

<li v-for="item in items" :key="item.id">{{ item.name }}</li>

Always use a stable unique key. Never use array index when order can change.


Slots

FeatureSyntax
Default slot<slot />
Named slot<slot name="header" />
Scoped slot<slot :item="item" />
Consumer default<template #default="{ item }">
Consumer named<template #header>
Dynamic slot<template #[name]>
Fallback<slot>Fallback</slot>

Computed

const doubled = computed(() => count.value * 2)

// Writable computed
const fullName = computed({
  get: () => `${first.value} ${last.value}`,
  set: (v) => { [first.value, last.value] = v.split(' ') },
})

Provide / Inject

// Provider
provide('key', value)
provide('key', readonly(ref))

// Consumer
const value = inject('key', defaultValue)

Teleport

<Teleport to="body">
  <div class="modal">...</div>
</Teleport>

Suspense

<Suspense>
  <template #default><AsyncComponent /></template>
  <template #fallback><Spinner /></template>
</Suspense>

KeepAlive

<KeepAlive :max="10">
  <component :is="current" />
</KeepAlive>

Transitions

ClassWhen
v-enter-fromEnter start
v-enter-activeEnter duration
v-enter-toEnter end
v-leave-fromLeave start
v-leave-activeLeave duration
v-leave-toLeave end
<Transition name="fade">
  <div v-if="show">Content</div>
</Transition>

Router Essentials

APIPurpose
useRouter()Router instance
useRoute()Current route
<RouterLink>Link
<RouterView>Route outlet
router.push()Navigate
router.replace()Navigate without history
beforeEachGlobal guard
// Route definition
const routes = [
  { path: '/', component: Home },
  { path: '/user/:id', component: User, props: true },
]

Pinia Essentials

import { defineStore } from 'pinia'

export const useCounter = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    double: (state) => state.count * 2,
  },
  actions: {
    increment() { this.count++ },
  },
})
APIPurpose
defineStore(id, options)Define store
storeToRefs(store)Destructure preserving reactivity
store.$patch({})Partial update
store.$reset()Reset to initial state

Compiler Macros

MacroPurpose
definePropsProps declaration
defineEmitsEmits declaration
defineExposePublic API
defineModelTwo-way binding
defineOptionsComponent options
defineSlotsTyped slots

Macros are compiled away; they have no runtime existence. Do not import them.


Compiler Optimizations

OptimizationEffect
Static HoistingStatic VNodes created once
Patch FlagsBitmask of dynamic properties
Tree FlatteningdynamicChildren array
Block TreeStructural directives create blocks

Patch Flags

FlagValue
TEXT1
CLASS2
STYLE4
PROPS8
FULL_PROPS16
HOISTED-1
BAIL-2

Internals: Reactivity

ConceptDetail
trackRecord effect against property (in get)
triggerSchedule effects (in set)
Target mapWeakMap → deps map → dep set
EffectScopeBoundary for cleanup
Orphaned effectsCreated outside scope, never stopped

Internals: Scheduler

ConceptDetail
queueJobPush update into queue
flushJobsRun queue, sorted by uid
MicrotaskPromise.resolve().then(flushJobs)
Parent firstSmaller uid runs first
nextTickReturns flush promise

Internals: Mount

FunctionPurpose
mountComponentEntry point
createComponentInstanceCreate instance
setupComponentRun setup()
setupRenderEffectCreate render effect
renderComponentRootRun render function
patchDiff and apply

script setup Binding Types

TypeTemplate Access
SETUP_REF.value
SETUP_LETisRef(x) ? x.value : x
SETUP_CONSTDirect
PROPS__props.x (inline) or $props.x
SETUP_REACTIVE_CONSTDirect

Vapor Mode

AspectDetail
Opt-in<script setup vapor>
Pure appcreateVaporApp()
Mixed appcreateApp().use(vaporInteropPlugin)
Runtime size~53% smaller
No VNodeDirect DOM operations
No Options APIOnly <script setup>
getCurrentInstance()Returns null

Performance Cheatsheet

Do

PracticeEffect
Stable :key in v-forCorrect DOM reuse
shallowRef for large dataNo deep proxy
markRaw for library instancesNo proxy wrapping
v-memo for large listsSkip unchanged items
computed for derived stateCached
Cleanup in onBeforeUnmountNo leaks

Don’t

Anti-PatternProblem
Array index as :keyWrong DOM reuse on reorder
ref() for large API dataDeep proxy overhead
watchEffect after awaitOrphaned effect
v-if + v-for on same elementv-if evaluates first
Mutating propsVue warns, parent state diverges
Deep watch on huge objectsPerformance cost

Lifecycle Cleanup Checklist

ResourceCleanup
addEventListenerremoveEventListener in onBeforeUnmount
setIntervalclearInterval
setTimeoutclearTimeout
Third-party instance.destroy()
WebSocket.close()
Observer.disconnect()
Effect outside scopeonScopeDispose

Common Gotchas

TrapReality
Destructuring reactive()Loses reactivity; use toRefs()
ref() vs toRef()ref() copies; toRef() syncs
unref() unwraps reactiveNo; only refs
watch on reactive objectImplicitly deep
watch on ref objectShallow by default
computed with side effectPure computation only
v-if + v-for same elementv-if has no loop scope
v-model on propUse defineModel()
defineProps destructureReactive in 3.5+ (compiler rewrites)
$attrs on multi-rootMust bind explicitly
v-html with user inputXSS risk; sanitize
nextTick before DOM readRequired after state change
provide with refProvide the ref, not .value

One-Page Flow

COMPONENT
  <script setup> → setup() → render effect → VNode → patch → DOM

REACTIVITY
  ref() → track on read → trigger on write → effect queued → flush

LIFECYCLE
  onMounted → onUpdated → onBeforeUnmount → onUnmounted

PERFORMANCE
  computed | shallowRef | markRaw | v-memo | stable :key

CLEANUP
  onBeforeUnmount → remove listeners, clear timers, destroy instances

Was this helpful?


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!