Vue.js Pocket Book — Uplatz
50 in-depth cards • Wide layout • Readable examples • 20-question interview Q&A included
1) What is Vue.js?
Vue is a progressive framework for building UIs. It combines a reactive data system, declarative templates, and component composition. Vue 3 introduced the Composition API, the new reactivity system (Proxies), and better TypeScript support.
<!-- CDN quick start -->
<script src="https://unpkg.com/vue@3"></script>
<div id="app">Hello {{ msg }}</div>
<script>
const { createApp, ref } = Vue;
createApp({ setup(){ const msg=ref('Vue'); return { msg } } }).mount('#app');
</script>
2) Declarative Templates
Vue templates compile to efficient render functions. Use directives like v-bind
, v-on
, v-if
, v-for
, and modifiers (.prevent
, .stop
) for expressive UIs.
<button :title="hint" @click.prevent="save">Save</button>
<li v-for="(u,i) in users" :key="u.id">{{ i+1 }}. {{ u.name }}</li>
3) Reactivity Basics
ref()
wraps a reactive primitive; reactive()
turns objects reactive. Access/assign via .value
for refs; objects unwrap in templates.
const n = ref(0); const state = reactive({ open:false });
watch(n, (nv, ov) => console.log('changed', ov, '→', nv));
4) Single File Components (SFC)
.vue
SFCs bundle template, script, and style. Use <script setup>
to get concise Composition API syntax and better treeshaking.
<template><button @click="count++">{{ count }}</button></template>
<script setup>import { ref } from 'vue'; const count = ref(0);</script>
5) Props & Emits
Define props and emitted events for parent-child communication. Validate props with types; declare emits for better DX.
<script setup>
defineProps({ label:String, modelValue:Boolean });
const emit = defineEmits(['update:modelValue']);
const toggle = () => emit('update:modelValue', !modelValue);
</script>
6) Computed & Watch
computed()
caches derived values until dependencies change. watch()
reacts to changes with side-effects. Use watchEffect()
for autoruns.
const full = computed(() => `${first.value} ${last.value}`);
watch(search, debounce(fetchList, 300));
7) Directives Deep Dive
Built-ins: v-if
, v-show
, v-for
, v-model
. Custom directives encapsulate low-level DOM effects (e.g., autofocus, lazy-load). Prefer components for complex logic.
app.directive('focus', { mounted(el){ el.focus(); } })
8) Lifecycle Hooks
Key Composition hooks: onMounted
, onUpdated
, onUnmounted
, onBeforeRouteLeave
(router). Avoid async race conditions by canceling work on unmount.
onMounted(() => fetchData()); onUnmounted(() => abortCtl.abort());
9) Slots & Provide/Inject
Slots compose content; scoped slots pass data down. Use provide/inject for deep dependency passing (theme, i18n), but keep it limited for clarity.
<slot name="footer" :count="items.length"></slot>
provide('theme', ref('light'))
10) Q&A — “When to use watch vs computed?”
Answer: Use computed for pure derivations used in templates or other code; use watch for side effects (fetching, logging, imperative DOM). If you’re assigning to state based on other state, try computed first.
11) Composables (useX)
Extract reusable logic into composable functions that return reactive state, methods, and computed values. Share across components without inheritance.
// useFetch.ts
export function useFetch(url){
const data = ref(null), error = ref(null), loading = ref(false);
const run = async() => { loading.value=true; try{ data.value=await (await fetch(url)).json() } catch(e){ error.value=e } finally{ loading.value=false } };
onMounted(run); return { data, error, loading, run };
}
12) Script Setup Essentials
<script setup>
runs once per SFC and auto-exposes top-level bindings to the template. Use defineProps/defineEmits
, defineExpose
, and withDefaults
for ergonomics.
<script setup lang="ts">
interface P{ size?:'sm'|'md'|'lg' }
const props = withDefaults(defineProps<P>(), { size:'md' })
defineExpose({ focus: () => input.value?.focus() })
</script>
13) Refs vs Reactive
Prefer ref
for primitives and reactive
for objects. When destructuring reactive, use toRefs()
to keep reactivity.
const state = reactive({ a:1, b:2 }); const { a, b } = toRefs(state);
14) v-model on Components
Support two-way binding by accepting modelValue
and emitting update:modelValue
. You can have multiple models with arguments.
<Child v-model="open" /> <!-- maps to modelValue -->
<Child v-model:title="title" v-model:count="n" />
15) Teleport & Suspense
Teleport renders children elsewhere in the DOM (modals/portals). Suspense coordinates async components and fallbacks.
<teleport to="body"><Modal v-if="open" /></teleport>
<Suspense><AsyncChart /><template #fallback>Loading…</template></Suspense>
16) Transitions
Animate enter/leave with the <transition>
component. Works with CSS classes or JS hooks; great for modal fades, list moves.
<transition name="fade"><div v-if="show">Hi</div></transition>
<style>.fade-enter-active,.fade-leave-active{transition:opacity .2s}.fade-enter-from,.fade-leave-to{opacity:0}</style>
17) Error Handling
Use errorCaptured
to catch child errors and provide fallbacks. For global errors, wrap app-level try/catch and log.
onErrorCaptured((err, inst, info) => { console.error(info, err); return false })
18) Performance Patterns
Prefer computed over watch, use v-memo
/keep-alive
for caching, and avoid large reactive objects; split stores and lazy routes.
<keep-alive include="UserList"><router-view /></keep-alive>
19) Accessibility
Manage focus on route changes, use semantic tags, ARIA roles for custom widgets, and keyboard shortcuts. Teleport modals should trap focus.
onMounted(() => document.getElementById('main')?.focus())
20) Q&A — “When to create a composable vs component?”
Answer: If the reuse is logic-only (fetching, timers, state), use a composable. If you need UI + logic reusable together, use a component. Combine both by using composables inside components.
21) Vue Router Basics
Define routes, nested routes, and dynamic params. Use router.push
for navigation and navigation guards for auth.
const router = createRouter({
history: createWebHistory(),
routes:[ { path:'/', component:Home }, { path:'/user/:id', component:User } ]
});
22) Route Guards
Global (beforeEach
), per-route (beforeEnter
), and in-component guards (onBeforeRouteLeave
). Check auth, preload data, or cancel navigation.
router.beforeEach((to,from,next)=> auth() ? next() : next('/login'))
23) Pinia Overview
Pinia is the official store for Vue. It’s modular (per-store), type-friendly, and works with Composition API. Use actions for async and getters for derived state.
export const useCart = defineStore('cart',{
state:()=>({ items:[] }),
actions:{ add(p){ this.items.push(p) } },
getters:{ total:(s)=> s.items.length }
})
24) Pinia + Persist
Persist stores with plugins (e.g., localStorage). Selectively persist keys and version data for migrations.
pinia.use(({ store }) => { store.$subscribe((_m, state)=> localStorage.setItem(store.$id, JSON.stringify(state))) })
25) Server Cache vs Client State
Server cache (e.g., fetching layer) stores remote data with lifetimes (stale-while-revalidate). Client state holds UI state and business rules. Don’t mix them.
// Keep filters/sort in Pinia; keep fetched lists in query cache
26) Fetching Patterns
Use onMounted
for initial loads, abort controllers on unmount, and exponential backoff. For SSR, fetch in route or page setup and serialize data.
const ctl = new AbortController();
onUnmounted(() => ctl.abort())
27) Forms & v-model
Use v-model
for inputs, modifiers (.trim
, .number
) for parsing, and custom components with modelValue
. Validate with Vuelidate or custom composables.
<input v-model.trim="email" type="email" />
28) Internationalization (i18n)
Vue I18n provides messages, pluralization, and lazy-loaded locales. Avoid recomputing on every render by memoizing formatters.
{{ $t('hello_user', { name }) }}
29) Accessibility Routing
Focus the main region on route change, keep landmarks, and announce route changes via ARIA live regions for screen readers.
<div id="main" tabindex="-1" aria-live="polite"><router-view /></div>
30) Q&A — “Pinia vs Vuex?”
Answer: Pinia is the modern successor: simpler API, first-class TS support, modular stores, no mutation boilerplate. Use Pinia unless you maintain legacy Vuex codebases.
31) Vite Tooling
Vite gives instant dev server via ES modules and fast HMR. Configure aliases, env vars (import.meta.env
), and code-splitting by route.
npm create vite@latest myapp -- --template vue-ts
32) TypeScript with Vue
Use vue-tsc
for SFC type-checking. Prefer <script setup lang="ts">
for clean inference and IDE hints.
npm i -D vue-tsc; npx vue-tsc --noEmit
33) Build Optimization
Code split by route, prefetch critical chunks, and treeshake unused components. Analyze bundles to spot heavy deps.
npm i -D rollup-plugin-visualizer
34) SSR / SSG Concepts
Server-side render initial HTML for speed/SEO, then hydrate on client. For content sites, use SSG to pre-generate pages at build time.
// Nuxt/Nitro or custom SSR with @vue/server-renderer
35) Nuxt Overview
Nuxt is a meta-framework for Vue: file-based routing, server/data fetching, SSR/SSG, and conventions for SEO and performance.
// pages/index.vue, server/api/*.ts for endpoints
36) Testing: Unit
Use Vitest/Jest + Vue Test Utils for component tests. Mount components with props, simulate events, assert DOM output.
import { mount } from '@vue/test-utils'
expect(mount(Counter).text()).toContain('0')
37) Testing: E2E
Playwright/Cypress for end-to-end tests. Seed fixture data, test routing, forms, and accessibility.
// cy.visit('/'); cy.findByRole('button', {name:/save/i}).click()
38) Linting & Formatting
ESLint + @vue/eslint-config, Prettier for consistent style. Enforce defineProps
types and component naming rules.
npm i -D eslint @vue/eslint-config-typescript prettier
39) CI/CD
Run type checks, unit/E2E tests, and build previews on every PR. Cache node_modules and Vite cache for speed.
# GitHub Actions: setup-node, cache, npm ci, npm run build, npm test
40) Q&A — “When pick Nuxt over Vite-only?”
Answer: Choose Nuxt if you need SSR/SSG, file-based routing, server APIs, and SEO out-of-the-box. Use Vite-only for SPAs or when you want minimal scaffolding and full control.
41) Recipe: Fetch + Cache Composable
A simple stale-while-revalidate approach: return cached data immediately, then refresh in background and notify dependents.
const cache = reactive(new Map());
export function useCache(key, loader){
const data = ref(cache.get(key)); const loading = ref(!data.value);
const refresh = async() => { loading.value=true; const v = await loader(); cache.set(key, v); data.value=v; loading.value=false; };
onMounted(refresh); return { data, loading, refresh };
}
42) Recipe: Debounced Input
Debounce queries to reduce chatter; cancel stale requests on new input.
const q = ref(''); watch(q, debounce(runSearch, 300));
43) Recipe: Modal with Teleport
Portal modal to body
, trap focus, and restore on close.
<teleport to="body"><Modal v-if="open" @close="open=false" /></teleport>
44) Recipe: Infinite List
Use IntersectionObserver composable to fetch next page and append items; show skeletons while loading.
const loadMore = async()=>{ page.value++; items.value.push(...await api(page.value)) }
45) Common Pitfalls
Mutating props, deep reactive structures causing perf issues, forgetting .value
on refs, heavy watchers, and global CSS leakage. Fix with computed, shallowRef/shallowReactive, and scoped CSS.
// Don't mutate props; emit updates instead
46) Security Basics
Sanitize user HTML, prefer server-side session cookies, protect API keys, and validate data before rendering. Vue escapes by default—avoid v-html
unless sanitized.
<div v-html="safeHtml"></div> <!-- safeHtml must be sanitized -->
47) Accessibility Checklist
Labels for inputs, keyboard nav, focus styles, high contrast, and ARIA roles for composites (tabs, dialog). Test with screen reader + keyboard only.
<button aria-expanded="open" :aria-controls="id">Toggle</button>
48) Production Checklist
Type-check, lint, test, analyze bundle, enable gzip/brotli, configure caching headers, handle errors/logging, and monitor Web Vitals.
import.meta.env.PROD // feature flags per env
49) Migration Tips (Vue 2 → 3)
Use the migration build, replace filters with computed/methods, move to Composition API gradually, update plugins to Vue 3 equivalents, and retest directives.
// Vue 2 filters → Vue 3 computed/formatters
50) Interview Q&A — 20 Practical Questions (Expanded)
1) Options vs Composition API? Options organizes by option type (data, methods); Composition organizes by feature logic via composables—better for scaling and TS.
2) When computed over watch? Use computed for pure derivations; watch for side effects or async flows.
3) Props down, events up? Parents pass props; children emit events back. For deep trees, consider provide/inject or a store (Pinia).
4) What does <script setup> do? Syntactic sugar for Composition API with better treeshaking and less boilerplate; top-level bindings are template-available.
5) How v-model works on components? It maps to modelValue
prop and update:modelValue
event; supports multiple arguments (e.g., v-model:title
).
6) Key differences Vue vs React? Vue uses templates with reactivity system and directives; React uses JSX and a different state model. Vue’s reactivity is automatic; React relies on state setters and reconciliation.
7) Why Pinia over Vuex? Simpler API, no mutations, first-class TS, modular stores; official recommendation for Vue 3.
8) Teleport use cases? Modals, tooltips, dropdowns that must escape overflow/stacking context.
9) Preventing unnecessary updates? Use computed, shallowRef
for large objects, v-memo
hints, and avoid creating new objects in templates.
10) SSR benefits? Faster first paint, SEO, and predictable content. Requires hydration and careful side-effect handling.
11) How to type props/emits? Use TS generics with defineProps<T>
and defineEmits<{ (e:'save', id:number):void }>()
.
12) Watch vs watchEffect? watch
tracks explicit sources; watchEffect
tracks dependencies automatically (good for quick reactive effects).
13) Handling async in setup? Run in hooks (onMounted
) or use async setup with Suspense; cancel on unmount.
14) Global state options? Pinia for app state; provide/inject for simple shared deps; avoid event buses for complex apps.
15) What is reactive caveat? Destructuring reactive objects breaks reactivity—use toRefs()
or keep as object.
16) Optimize lists? Always use stable :key
, virtualize long lists, and avoid heavy work in item components.
17) Handling forms? v-model
with modifiers, validation composables, and debounced submits; keep source of truth in component or store by need.
18) Error boundaries? Use errorCaptured
in parent; provide fallback UI and logging. For global, app-level handlers.
19) Security with v-html? Vue escapes by default; v-html
does not—sanitize and trust only safe sources.
20) When to choose Nuxt? For SSR/SSG, SEO, conventions, server API integration, and DX with file-based routing. Otherwise Vite SPA is fine.