64 Vue.js interview questions with detailed answers, sorted from basic to advanced. Free to practice, with progress saved automatically.
Vue.js is a JavaScript framework for building interfaces from components on top of a reactivity system. The questions cover core concepts, directives such as v-if and v-model, the Composition API and composables, reactivity internals, component communication, Pinia, Vue Router, SSR with Nuxt, and performance techniques like v-memo.
and 5 more topics.
Vue.js is a JavaScript framework for building UIs that calls itself a "progressive framework": you can drop it into part of an existing HTML page, or use it to build a full SPA. Vue React Angular ------------ What it is Framework, usable piece by piece…
The Options API groups code by option type (data, methods, computed); the Composition API groups code by feature, declaring state and functions directly in <script setup. Both run on the same system; in fact the Options API is built on top of the Composition API.…
<script setup is the compile-time shorthand for the Composition API in Single-File Components: the compiler turns the whole script block into a setup() function, and every top-level variable, function and import is usable in the template. Both versions behave the same; the compiler generates the…
A Single File Component (SFC) is a .vue file that keeps the three parts of a component in one place: template (HTML), script (logic) and style (CSS). Browsers cannot read .vue files, so a build tool (Vite with @vitejs/plugin-vue, or webpack's vue-loader) compiles them into…
A directive is a special attribute starting with v- in a Vue template. It ties the DOM to state: when state changes, Vue updates the DOM. - v-if / v-else: a false condition removes the element from the DOM; true creates it again. Good for…
v-if: fully removes DOM when false — high toggle cost but skips rendering children when not needed (lazy). v-show: only toggles display:none — DOM always rendered, low toggle cost. Use v-show when toggling frequently. Use v-if when the condition rarely changes, or when child components…
:key is how you tell Vue which item is which between two renders. When a list changes, Vue compares the old and new virtual nodes (vnodes); with keys it matches each old item to its new counterpart, then only adds, removes or moves the DOM…
v-model is shorthand: :modelValue + @update:modelValue. Default for input: For a custom component v-model, since Vue 3.4 use defineModel(). It returns a ref: reading it gives the value passed by the parent, assigning to it emits update:modelValue to the parent. Vue 3 supports multiple v-models:…
Vue 3 wraps objects in a Proxy, a wrapper that intercepts every read (get) and write (set). On read, Vue tracks: it records which effect is reading that property (an effect is a render function, a computed or a watcher). On write, Vue triggers: it…
ref: wraps any value (primitive or object) in an object with a .value property. In script you access it via .value; in the template Vue unwraps it automatically. reactive: turns an object/array into a reactive Proxy, accessed directly with no .value. Current recommendation: the official…
All three react when reactive state changes, but they serve different purposes: computed produces a new value from state, while watch and watchEffect run side effects (API calls, writing localStorage, touching the DOM) when state changes. fullName recomputes when firstName or lastName changes, and it…
A composable is a function that uses the Composition API (ref, computed, lifecycle hooks...) to package stateful logic and reuse it across components. By convention its name starts with use, like useFetch or useMouse. Each call to useFetch creates its own data/loading pair, so the…
In the Composition API, lifecycle hooks are onXxx functions imported from vue and called inside setup() (or <script setup). Each one takes a callback, and Vue calls it when the component reaches that stage. This component reads the window size once it is attached to…
provide / inject let a component supply a value (provide) that any descendant can pick up directly (inject), without passing props through every layer in between (prop drilling). Parent passes no props, yet Child can read theme and call toggleTheme. When the button is clicked,…
defineProps declares the props a component receives; defineEmits declares the events it can emit. Both are compile-time macros that only work inside <script setup: they need no import, and the Vue compiler replaces them with real code at build time. Declaring with types as above…
How you pass data in Vue depends on how the two components are related. The most basic pair is props (parent passes down to child) and emit (child reports an event up to the parent). The parent owns total and passes it down via the…
Slots let a parent component pass content into a predefined spot in a child component's template. Default slot: <slot /. Named slots: <slot name="header" / — parent uses <template header. Scoped slot: child passes data up to parent through slot: Use scoped slots when child…
In <script setup, components are closed by default: even when the parent gets the child instance through a template ref, it cannot read any variable or function inside. Vue does this so the parent does not depend on the child's internals. defineExpose names exactly which…
Vue Router is Vue's official router: it matches the URL to a component and displays it without reloading the page. Setup takes three things: declare the route table, plug the router into the app, and place somewhere to display the result. - app.use(router): the step…
Navigation guards are hooks Vue Router calls around each route change, used for auth checks, redirects or cancelling navigation. There are three levels: global, per-route and in-component. In-component guards (Options API): beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave. In Composition API use onBeforeRouteLeave, onBeforeRouteUpdate; there is no onBeforeRouteEnter because…
Dynamic segment: path: '/user/:id' — in <script setup read it via const route = useRoute() and then route.params.id. Lazy loading with dynamic import: Lazy loading: the component is only downloaded when navigating to that route — reduces initial bundle size.
Pinia is Vue 3's official state management library, holding state many components share (the logged-in user, a cart). It replaced Vuex because it has less boilerplate and fits the Composition API. The store reads like a composable: ref is state, computed is a getter, a…
Use defineStore() with setup-store syntax (recommended) — refs become state, computed values become getters, functions become actions. Pitfall: destructuring store loses reactivity — use storeToRefs: const { count, double } = storeToRefs(store) (methods can be destructured normally).
storeToRefs(store) turns a Pinia store's state and getters into individual refs, so you can destructure them into variables while keeping reactivity. You need it because a store is a reactive object. Destructuring straight from it only copies the values at that moment into plain variables,…
v-memo skips re-rendering a part of the template when its dependency array has not changed since the last render. The idea is like React.memo, but declared right in the template: Use it when: - The list is long and each row is expensive to render.…
<KeepAlive keeps a component instance in memory instead of unmounting it when you switch to another component, so its state (half-typed text, form values) is still there when you come back. Without it, switching components unmounts the old instance and the next visit creates a…
Use dynamic import to lazy load components — only download when needed: The most common place to lazy load is routes: in Vue Router write component: () = import('./views/Dashboard.vue'). Each page becomes its own chunk, loaded only when the user visits it, with no defineAsyncComponent…
Vue handles errors error-boundary style through the errorCaptured hook (Options API) or onErrorCaptured (Composition API). The hook only catches errors from descendant components, not from the component that registers it: Compare with app.config.errorHandler = (err, instance, info) = { ... }: this is the app-wide…
Testing a Vue component means mounting it into a fake DOM (happy-dom or jsdom), interacting with it like a user, and then checking what a user can observe: the rendered output and the events the component emits. Vitest is the test runner (it runs tests…
nextTick returns a Promise that resolves after Vue has finished updating the DOM for the current state changes. You need it because Vue does not update the DOM the moment state changes. Vue batches all changes made during the same synchronous run and renders once…
toRef: creates a ref from a property of a reactive object. The ref is two-way connected to the original property; reads and writes go straight to state: toRefs: turns every property of a reactive object into its own ref; use it when destructuring so reactivity…
Accessibility (a11y) in Vue is mostly HTML accessibility: Vue only renders DOM, so screen readers and keyboards understand only what the DOM expresses. The Vue-specific part is wherever the DOM changes dynamically: open/closed state, focus after re-render, content that updates. The example shows three things…
Template refs give direct access to a DOM element or a child component's instance. Declare a ref with the same name as the ref attribute in the template, and Vue assigns the element to it after mount: A component using <script setup is closed by…
The standard pattern for fetching async data in Vue 3 Composition API is to use onMounted with try/catch/finally, or extract it into a reusable composable. The if (!res.ok) line is required: fetch only rejects on network errors; when the server returns 404 or 500 the…
Vue auto-unwraps refs in certain contexts. Knowing where it does and where it does not avoids bugs: Template auto-unwrap: refs declared at the top level of <script setup are unwrapped in the template, no .value needed: Template unwrapping only applies to refs that are top-level…
Route meta attaches custom data to routes — commonly used for auth, breadcrumbs, titles:
Vue Router lets you control the scroll position on each navigation through the scrollBehavior option: Returning savedPosition on back/forward puts users back where they were reading on the previous page, matching what the browser does for full page loads. scrollBehavior can also return a Promise.…
Use InjectionKey for typed provide/inject and to avoid string key collisions: Use a Symbol as the key instead of a string: every Symbol is unique, so two libraries or modules that both pick the key 'theme' cannot overwrite each other. This matters in large apps…
v-once renders an element or component exactly once and skips every later update; after the first render that part is treated as static content. v-pre skips compilation for the whole subtree, so mustache syntax is printed literally: Difference: v-once still compiles, renders once and then…
A v-model modifier is a dot suffix that transforms the value before it is assigned. Vue has three built-in modifiers for input elements and lets components define their own. The three built-ins: - .lazy: syncs on the change event (blur or Enter) instead of on…
Because in Vue 3 v-if has higher priority than v-for — the condition is evaluated first, so it cannot see the loop variable. The snippet below throws because user does not exist yet when v-if runs: Two fixes: Option 1 also performs better: the computed…
Vue enforces one-way data flow: props travel from parent to child only. In dev mode, Vue wraps props in a read-only proxy, so the assignment props.title = ... is blocked (the value does not change) and Vue only logs a console warning; it does not…
Because reactive() returns a Proxy — reactivity lives in property access through the proxy, not in the value. Destructuring copies the primitive at that moment, severing the link: How to keep the link: Same for props: before Vue 3.5, const { title } = defineProps()…
Three things that trip people up when watching object data: 1. deep. Watching a ref holding an object fires only when the whole object is replaced (obj.value = {...}). Changing a nested property does not trigger it unless you pass { deep: true }. When…
defineModel() is a macro (stable since Vue 3.4) that bundles exactly the prop + emit pair you used to declare by hand, and returns a two-way ref. What actually differs: - Writing model.value = x emits automatically; reading it returns the current prop value. No…
A setup store uses plain setup() syntax: ref is state, computed is a getter, a function is an action. Whatever you want public must be returned. Compared with an option store ({ state, getters, actions }): - More flexible: you can use watch, other composables,…