[{"data":1,"prerenderedAt":433},["ShallowReactive",2],{"all-questions-vue":3},{"beginner":4,"intermediate":175,"advanced":319},[5,16,23,31,40,49,56,64,73,82,92,102,111,120,128,135,145,155,165],{"id":6,"category":7,"question":8,"answer":9,"level":10,"tags":11},1,"Basics","What is Vue.js and how does its architecture differ from React or Angular?","## Core Concept\nVue.js is a progressive JavaScript framework for building user interfaces. It is designed from the ground up to be incrementally adoptable. The core library focuses on the view layer only, but integrates easily with libraries or existing projects.\n\n**Key architecture differences:**\n- **Vue vs React:** Vue uses templates (HTML-based) while React uses JSX. Vue's reactivity is automatic via `ref`\u002F`reactive`; React requires hooks and explicit dependency arrays. Vue's component styles are scoped natively; React relies on CSS-in-JS or libraries.\n- **Vue vs Angular:** Vue is simpler and more flexible, without the heavy concepts like modules, dependency injection, or TypeScript mandates. Angular uses real DOM with Zones; Vue uses a virtual DOM with fine-grained reactivity.\n\n## Syntax\nVue Single-File Component (SFC) structure:\n```vue\n\u003Cscript setup>\nimport { ref } from 'vue'\nconst count = ref(0)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cbutton @click=\"count++\">Clicked {{ count }} times\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003Cstyle scoped>\nbutton { color: red; }\n\u003C\u002Fstyle>\n```\n\n## Execution Flow\n1. **Compilation phase:** Vue compiler transforms SFC `\u003Ctemplate>` into JavaScript render functions.\n2. **Reactivity setup:** `ref`\u002F`reactive` creates reactive proxies that track dependencies.\n3. **Render phase:** Render function executes, creating a virtual DOM tree.\n4. **Mounting:** Virtual DOM converted to real DOM elements inserted into the page.\n5. **Update phase:** When reactive state changes, Vue schedules a re-render, diffs the virtual DOM, and applies minimal DOM updates.\n\n## Reactivity Explanation\nVue 3 uses a **Proxy-based reactivity system**. When you call `ref(0)`, Vue creates a `RefImpl` object that wraps the value and provides getter\u002Fsetter traps. The getter collects current effect (like the component's render function) as a dependency. The setter triggers queued re-execution of that effect.\n\n## Practical Usage\n- Building interactive dashboards\n- Form-heavy applications with two-way binding\n- Incrementally enhancing server-rendered pages\n- Full single-page applications with Vue Router\n\n## Interview Insight\nInterviewers ask this to gauge your understanding of Vue's positioning in the ecosystem. Emphasize **progressive adoption** – you can use Vue without a build step via CDN, or scale up to a full SPA. Compare reactivity models (Proxy vs `setState` vs Zones).\n\n## Common Mistakes\n- Assuming Vue 2 vs Vue 3 APIs are identical (Vue 3 no longer uses `Vue.set`)\n- Overusing reactive objects when simple refs suffice\n- Expecting React-like `setState` batching (Vue batches automatically but differently)\n\n## Best Practices\n- Start with `ref` for all primitives and objects; only use `reactive` for complex objects where you want direct property access without `.value`\n- Use `\u003Cscript setup>` for all new components\n- Keep templates declarative with minimal logic inside `{{ }}`\n\n## Performance Considerations\nVue's virtual DOM is highly optimized with compile-time hints (patch flags, block tree). It's generally fast enough without manual optimization. However, avoid deep nesting of large lists; use virtualization for > 1000 items.\n\n## Production Recommendations\n- Use Vue CLI or Vite with production build (`vite build`)\n- Enable `vue\u002Fcompiler-sfc` template optimization\n- Code-split routes with dynamic imports\n- Use `shallowRef` for large arrays that don't need deep reactivity\n\n## Latest Vue Patterns\n- Composition API with `\u003Cscript setup>` is now standard (Options API legacy)\n- `defineModel` for two-way binding (Vue 3.4+)\n- `toValue` utility for handling `MaybeRefOrGetter`\n\n## Interview Tip\nMention that Vue is **not opinionated about routing or state** for small projects, but officially supports Vue Router and Pinia for scale. Also note that Vue 3 has **smaller runtime size** (~20KB gzipped core) than React or Angular.\n\n## Common Follow-up\n*\"How does Vue's change detection compare to React's?\"* – React re-runs the whole component function on state change, requiring manual memoization (`useMemo`, `useCallback`) to skip children. Vue tracks mutable state and automatically knows which components need re-rendering, often resulting in fewer unnecessary updates.\n\n## Real-world Example\nA product list with filter:\n```vue\n\u003Cscript setup>\nimport { ref, computed } from 'vue'\nconst products = ref([{ name: 'Laptop', price: 1000 }])\nconst search = ref('')\nconst filtered = computed(() => \n  products.value.filter(p => p.name.includes(search.value))\n)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cinput v-model=\"search\" placeholder=\"Filter\">\n  \u003Cdiv v-for=\"product in filtered\" :key=\"product.name\">{{ product.name }}\u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nVue 3's compiler can also compile template syntax into **hand-written render functions** for maximum performance. The reactivity system is fully standalone (`@vue\u002Freactivity`) – you can use it outside Vue for plain JS state management.","beginner",[12,13,14,15],"basics","architecture","vue3","comparison",{"id":17,"category":7,"question":18,"answer":19,"level":10,"tags":20},2,"Explain the Vue instance and the role of the `createApp` function in Vue 3.","## Core Concept\nThe Vue application instance is the root of every Vue application. In Vue 3, `createApp` creates a new application instance that serves as the context for registering global components, directives, plugins, and mounting the root component to the DOM.\n\n**Why `createApp` instead of `new Vue()`?** Vue 2 used a global Vue constructor, which caused configuration mutation (e.g., `Vue.use`, `Vue.mixin`) that polluted all instances. Vue 3 isolates configuration per app, preventing cross-app contamination.\n\n## Syntax\n```js\nimport { createApp } from 'vue'\nimport App from '.\u002FApp.vue'\n\nconst app = createApp(App)\n\n\u002F\u002F Global registration\napp.component('MyButton', MyButton)\napp.directive('focus', focusDirective)\napp.use(router) \u002F\u002F plugin\napp.provide('theme', 'dark')\n\n\u002F\u002F Mount to DOM element\napp.mount('#app')\n```\n\n## Execution Flow\n1. `createApp(App)` initializes a new app context with:\n   - Reactivity system (global `effect` scope)\n   - Component registry (empty initially)\n   - Directive registry\n   - Provide\u002FInject store\n2. The component object (`App`) is set as the root component.\n3. `app.mount('#app')` does:\n   - Finds the DOM element (or creates one)\n   - Compiles the root component's template if not already compiled\n   - Creates the root component instance\n   - Sets up reactivity and lifecycle hooks\n   - Renders the virtual DOM and replaces `#app` with the generated DOM\n\n## Reactivity Explanation\nEven at the app level, `createApp` initializes a global reactive effect scope. Any global state (via `provide`) or config changes are reactive. When the root component mounts, its render effect is tracked in the app's effect scope.\n\n## Practical Usage\n- Multi-app patterns on the same page (micro-frontends):\n```js\nconst app1 = createApp(App1).mount('#app1')\nconst app2 = createApp(App2).mount('#app2')\n```\n- Testing: Create a fresh app per test to isolate side effects.\n- Lazy loading: Dynamically create and mount apps on demand.\n\n## Interview Insight\nHighlight the **isolation advantage** over Vue 2. Also mention that `createApp` returns an `App` instance with a chainable API (like `.use().component().mount()`).\n\n## Common Mistakes\n- Mounting to a body or html element (should be a dedicated div)\n- Forgetting to call `mount` after configuration\n- Using Vue 2 patterns like `new Vue({ ... })`\n\n## Best Practices\n- Only one `createApp` call per Vue application instance\n- Perform all global registrations before `mount`\n- Use `app.unmount()` to clean up in long-running SPAs or tests\n- Store the app instance if you need to unmount or provide async injection\n\n## Performance Considerations\n`createApp` is lightweight. However, registering many global components adds startup cost. Prefer local imports inside SFCs unless components are truly app-wide (e.g., UI library).\n\n## Production Recommendations\n- In production builds, templates are pre-compiled, so `mount` simply hydrates or renders.\n- For SSR, use `createSSRApp` instead of `createApp` for server-compatible hydration.\n- Avoid dynamic unmounting\u002Fremounting of the root app in production; design as a single SPA.\n\n## Latest Vue Patterns\n- `createApp` now supports passing a root component with `\u003Cscript setup>` without extra configuration.\n- Vue 3.3+ allows `app.unmount()` to properly clean up the entire app's effect scope.\n\n## Interview Tip\nWhen asked about `createApp`, immediately contrast with Vue 2's global contamination problem. This shows deep understanding of the framework's evolution.\n\n## Common Follow-up\n*\"Can I have multiple Vue apps on one page?\"* – Yes, each isolated. They can communicate via custom events or shared external stores (Pinia with global state).\n\n## Real-world Example\nEmbedding a Vue widget in a legacy jQuery page:\n```js\n\u002F\u002F widget.js\nimport { createApp } from 'vue'\nimport Widget from '.\u002FWidget.vue'\n\nwindow.initWidget = (elementId, initialProps) => {\n  const app = createApp(Widget, initialProps) \u002F\u002F pass props via second arg\n  app.mount(`#${elementId}`)\n  return app \u002F\u002F for later unmount\n}\n```\n\n## Advanced Notes\nThe `App` instance returned by `createApp` is not a Vue component instance; it's a **container**. You cannot access component methods or data from it. For that, use `app._component` (private) or better, use component refs after mounting.",[12,21,14,22],"createApp","app-instance",{"id":24,"category":7,"question":25,"answer":26,"level":10,"tags":27},3,"What are Vue template syntax, interpolation, and directives?","## Core Concept\nVue uses an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying component state. Templates are valid HTML and are parsed by Vue's compiler into optimized render functions.\n\n**Interpolation** (mustache syntax `{{ }}`) renders reactive data as text. **Directives** are special attributes with the `v-` prefix that apply reactive behavior to the DOM (e.g., `v-bind`, `v-on`, `v-if`).\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { ref } from 'vue'\nconst message = ref('Hello Vue')\nconst isVisible = ref(true)\nconst url = ref('https:\u002F\u002Fvuejs.org')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003C!-- Text interpolation -->\n  \u003Cp>{{ message }}\u003C\u002Fp>\n  \n  \u003C!-- Raw HTML (use v-html cautiously) -->\n  \u003Cdiv v-html=\"rawHtml\">\u003C\u002Fdiv>\n  \n  \u003C!-- Attribute binding using v-bind or shorthand : -->\n  \u003Ca :href=\"url\">Link\u003C\u002Fa>\n  \n  \u003C!-- Event binding using v-on or shorthand @ -->\n  \u003Cbutton @click=\"message = 'Updated'\">Update\u003C\u002Fbutton>\n  \n  \u003C!-- Conditional directive -->\n  \u003Cp v-if=\"isVisible\">Now you see me\u003C\u002Fp>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. Template is parsed by Vue compiler into an **AST** (Abstract Syntax Tree).\n2. Static parts (no bindings) are hoisted to reduce re-render cost.\n3. Dynamic parts are transformed into `_createElementVNode` calls with patch flags.\n4. During render, reactive values are inserted into the DOM via text nodes or attribute setters.\n5. When state changes, Vue updates only the specific DOM nodes (not recompiling the template).\n\n## Reactivity Explanation\nThe `{{ }}` interpolation creates a **text node** that is linked to the reactive source. Vue's reactivity system tracks that the component's render effect reads `message.value`. When `message` changes, the effect re-runs, updating the text node content without touching other DOM.\n\n## Practical Usage\n- Displaying dynamic data in dashboards\n- Form input value binding with `v-model` (sugar for `:value` + `@input`)\n- Conditional UI sections using `v-if`\u002F`v-else`\n- Iterating lists with `v-for`\n\n## Interview Insight\nExplain that Vue templates are **compile-time optimized** – unlike runtime template engines, Vue's compiler adds static hoisting and patch flags. This makes Vue templates fast without manual optimizations.\n\n## Common Mistakes\n- Using `{{ }}` inside HTML attributes (use `v-bind`)\n- Forgetting that `v-html` can lead to XSS – sanitize user input\n- Overusing expressions inside `{{ }}` (keep simple; use computed for logic)\n- Using `v-if` and `v-for` on same element (they have different precedence; `v-if` takes priority in Vue 3)\n\n## Best Practices\n- Prefer shorthand `:` for `v-bind` and `@` for `v-on`\n- Keep templates declarative; move complex logic to computed props\n- Use `v-once` for static content that never updates (performance boost)\n- Use `v-memo` for memoizing sub-trees\n\n## Performance Considerations\n- Directives like `v-if` ensure lazy destruction\u002Fcreation, good for infrequent toggles.\n- `v-show` keeps element in DOM with `display: none`, better for frequent toggles.\n- Avoid large template expressions – each re-evaluates on every render.\n\n## Production Recommendations\n- Enable template compilation at build time (`vue-loader` or `@vitejs\u002Fplugin-vue`) – never compile templates in production.\n- Use `v-pre` for large static blocks to skip compilation.\n- Lint templates with `eslint-plugin-vue` to prevent directive mistakes.\n\n## Latest Vue Patterns\n- **v-bind with object**: `\u003Cdiv v-bind=\"{ id: 'foo', class: 'bar' }\">`\n- **Dynamic directive arguments**: `\u003Ca @[eventName]=\"handler\">`\n- **Custom modifiers** on directives (advanced)\n\n## Interview Tip\nHighlight the difference between `v-if` (real conditional rendering) and `v-show` (CSS-based). Interviewers often ask about performance implications of both.\n\n## Common Follow-up\n*\"What is the difference between `v-bind` and interpolation?\"* – Interpolation only sets text content; `v-bind` sets any attribute or prop, including HTML attributes, DOM properties, and custom component props.\n\n## Real-world Example\nProduct card with conditional availability:\n```vue\n\u003Ctemplate>\n  \u003Cdiv class=\"product\">\n    \u003Ch3>{{ name }}\u003C\u002Fh3>\n    \u003Cp :class=\"{ discounted: hasDiscount }\">{{ price }}\u003C\u002Fp>\n    \u003Cbutton @click=\"addToCart\" :disabled=\"!inStock\">\n      {{ inStock ? 'Add to cart' : 'Sold out' }}\n    \u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nVue 3's template explorer (online tool) shows how directives transform into render functions. For example, `v-if` becomes a ternary operator inside the render function, while `v-for` becomes a `map` call. Understanding this helps debugging strange behavior.",[28,29,30],"template-syntax","directives","interpolation",{"id":32,"category":7,"question":33,"answer":34,"level":10,"tags":35},4,"Explain v-bind and v-on directives with examples.","## Core Concept\n`v-bind` (shorthand `:`) dynamically binds one or more attributes, props, or component properties to an expression. `v-on` (shorthand `@`) attaches event listeners to DOM events or component custom events.\n\n**Key insight:** `v-bind` sets JavaScript expressions as values, not static strings. `v-on` accepts inline statements, method names, or complex expressions with access to event object.\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { ref } from 'vue'\nconst imgSrc = ref('\u002Flogo.png')\nconst altText = 'Vue logo'\nconst isDisabled = ref(false)\nconst count = ref(0)\n\nfunction handleClick(event) {\n  console.log('Clicked at', event.clientX)\n  count.value++\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003C!-- v-bind examples -->\n  \u003Cimg :src=\"imgSrc\" :alt=\"altText\">\n  \u003Cbutton :disabled=\"isDisabled\">Submit\u003C\u002Fbutton>\n  \u003Cdiv :class=\"{ active: isActive, 'text-bold': true }\">Dynamic class\u003C\u002Fdiv>\n  \u003Cdiv :style=\"{ color: textColor, fontSize: size + 'px' }\">Inline style\u003C\u002Fdiv>\n  \n  \u003C!-- v-on examples -->\n  \u003Cbutton @click=\"count++\">Increment (inline)\u003C\u002Fbutton>\n  \u003Cbutton @click=\"handleClick\">Method handler\u003C\u002Fbutton>\n  \u003Cbutton @click=\"handleClick($event, 'extra')\">With args\u003C\u002Fbutton>\n  \u003Cinput @keyup.enter=\"submit\">\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n**v-bind:**\n1. At compile time, Vue detects `:attr` and creates a binding in the render function.\n2. During render, the expression is evaluated in the component's reactive context.\n3. If the attribute is a standard HTML attribute, Vue sets it via `setAttribute`. For DOM properties (like `disabled`), Vue sets the property directly.\n4. When the bound value changes, Vue updates only that attribute\u002Fproperty without re-rendering the whole element.\n\n**v-on:**\n1. Vue attaches real DOM event listeners using `addEventListener` during mounting.\n2. When the event fires, Vue invokes the associated handler with the correct `this` binding (component instance).\n3. For inline statements, Vue creates a wrapper function that executes the statement in component context.\n4. Event modifiers (`.prevent`, `.stop`) are implemented as wrapper logic before calling the handler.\n\n## Reactivity Explanation\nBoth directives rely on Vue's reactivity: `v-bind` re-evaluates when its dependency changes; `v-on` does not track dependencies because it's a side effect trigger, not a consumer of reactive data (unless the handler itself reads reactive data, which is fine).\n\n## Practical Usage\n- **v-bind:** Binding image `src`, anchor `href`, form input `value`, ARIA attributes, custom component props\n- **v-on:** Handling clicks, form submissions, keyboard events, mouse events, touch events\n\n## Interview Insight\nEmphasize that `v-bind` works with **any attribute**, including custom ones like `data-*`. Also note that `v-on` can listen to custom events from child components (`@custom-event=\"handler\"`).\n\n## Common Mistakes\n- Forgetting colon: `href=\"url\"` binds static string `\"url\"`, not the variable `url`.\n- Using `v-on` without method: `@click=\"() => doSomething\"` creates new function on every render (use `@click=\"doSomething\"` instead).\n- Overusing `$event` – most handlers receive event automatically unless you pass other args.\n\n## Best Practices\n- Use shorthand always (`:` and `@`) for brevity.\n- Prefer method handlers over inline JavaScript unless very simple (e.g., `count++`).\n- Use event modifiers (`.prevent`, `.stop`, `.once`, `.self`) instead of manually calling `preventDefault` in methods.\n- For `v-bind`, use object syntax for multiple related attributes: `v-bind=\"{ id, class }\"`.\n\n## Performance Considerations\n- `v-bind` is cheap – attribute updates are fast.\n- `v-on` has initial cost of attaching listeners. Avoid dynamically adding\u002Fremoving many listeners; use conditional rendering instead.\n- Debounce or throttle handlers for high-frequency events (e.g., `@scroll`).\n\n## Production Recommendations\n- Use `.passive` modifier for scroll\u002Ftouch events to improve scrolling performance: `@touchstart.passive`.\n- For components, prefer emitting events (`emit`) over passing callbacks as props.\n- In production, all event handlers are minified and optimized.\n\n## Latest Vue Patterns\n- **v-bind with same name shorthand** (Vue 3.4+): `:id` instead of `:id=\"id\"` when variable name matches attribute name.\n- **`defineModel` macro** reduces need for `:value` + `@update:modelValue` boilerplate.\n- **Key modifier aliases** for `v-on`: `.enter`, `.tab`, `.delete`, `.esc`, `.space`, `.up`, `.down`, `.left`, `.right`.\n\n## Interview Tip\nWhen asked to explain both, show how they work together: `v-bind` for data flow (parent→child), `v-on` for event flow (child→parent). This is the foundation of Vue's one-way data flow with two-way binding via `v-model`.\n\n## Common Follow-up\n*\"What is the difference between `@click` and `@click.native`?\"* – In Vue 2, `.native` was needed for native events on components. Vue 3 removed it; component events now require explicit `emits` declaration, and native listeners are automatically applied to the root element.\n\n## Real-world Example\nA login form with validation and submission:\n```vue\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"handleLogin\">\n    \u003Cinput \n      type=\"email\" \n      :value=\"email\" \n      @input=\"email = $event.target.value\"\n      :class=\"{ error: emailError }\"\n    >\n    \u003Cbutton :disabled=\"!isFormValid\" @click=\"login\">Login\u003C\u002Fbutton>\n  \u003C\u002Fform>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { ref, computed } from 'vue'\nconst email = ref('')\nconst emailError = computed(() => !email.value.includes('@'))\nconst isFormValid = computed(() => !emailError.value)\n\nfunction handleLogin() { \u002F* API call *\u002F }\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\n`v-bind` also works with **component v-model binding** – `\u003CChild v-model:title=\"bookTitle\">` compiles to `:title` + `@update:title`. `v-on` supports **key aliases** and **exact modifiers** (`@click.ctrl.exact` for exact Ctrl without Alt\u002FShift). The event object is accessible as `$event` in inline statements.",[29,36,37,38,39],"v-bind","v-on","events","attributes",{"id":41,"category":7,"question":42,"answer":43,"level":10,"tags":44},5,"How does one-way data binding vs two-way binding work in Vue?","## Core Concept\n**One-way data binding** means data flows from component to template (or parent to child) in a single direction. **Two-way binding** means data flows both ways: from component to template and from template (user input) back to component.\n\nVue implements one-way binding via `v-bind` (props\u002Fattributes) and two-way binding via `v-model`, which is syntactic sugar for `:value` + `@input` (on form elements).\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { ref } from 'vue'\nconst message = ref('Hello')\nconst name = ref('')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003C!-- One-way binding: message flows to input, but changes don't update message -->\n  \u003Cinput :value=\"message\" @input=\"message = $event.target.value\">\n  \n  \u003C!-- Same as above, but using v-model (two-way) -->\n  \u003Cinput v-model=\"message\">\n  \n  \u003C!-- One-way with text content -->\n  \u003Cp>{{ message }}\u003C\u002Fp>  \u003C!-- message changes only from JS -->\n  \n  \u003C!-- Two-way on custom component -->\n  \u003CCustomInput v-model=\"name\" \u002F>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n**One-way:**\n1. Parent passes data via prop using `:propName=\"value\"`.\n2. Child receives prop and renders it.\n3. If parent changes the value, child re-renders with new value.\n4. If child tries to modify the prop, Vue warns (mutation not allowed).\n\n**Two-way (v-model):**\n1. Vue creates a binding: `:value` (or `:modelValue` for components) and `@input` (or `@update:modelValue`).\n2. On user input, the event handler updates the bound variable.\n3. The variable change triggers reactivity, updating the input value.\n4. This creates a loop that synchronizes both directions.\n\n## Reactivity Explanation\nOne-way relies on Vue's reactive getters (reading the value) – no back-propagation. Two-way involves both a getter (for value) and a setter (via event handler). The `v-model` directive tells Vue to treat the bound variable as the single source of truth, updating it on DOM events.\n\n## Practical Usage\n- **One-way:** Displaying data, passing props to children, computed properties, static attributes\n- **Two-way:** Form inputs (text, checkbox, radio, select), custom input components, UI controls like sliders or toggles\n\n## Interview Insight\nExplain that Vue's **default is one-way flow** for props (parent→child) and events (child→parent). `v-model` is an abstraction on top of this, not a violation. This aligns with React's unidirectional data flow but with less boilerplate.\n\n## Common Mistakes\n- Mutating a prop directly in child (breaks one-way flow)\n- Using `v-model` on non-form elements without proper event handling\n- Forgetting that `v-model` on components defaults to `modelValue` prop and `update:modelValue` event\n- Overusing two-way when one-way + explicit events would be clearer\n\n## Best Practices\n- Use one-way binding for display-only data\n- Use `v-model` for form inputs and custom input-like components\n- Prefer `defineModel` (Vue 3.4+) over manual `modelValue` + `update:` for simpler two-way binding in components\n- Avoid deep two-way binding on complex objects (use events for mutations)\n\n## Performance Considerations\nOne-way binding has less overhead (no event listener setup for the return path). Two-way adds event listeners but is negligible for typical forms. For high-frequency inputs (e.g., real-time search), both perform equally well.\n\n## Production Recommendations\n- For complex forms, use two-way binding with `v-model` but consider debouncing or using `v-model.lazy` to sync on `change` instead of `input`.\n- In component libraries, expose `v-model` support for better developer experience.\n- Use `v-model` with modifiers (`.trim`, `.number`, `.lazy`) to reduce manual transformations.\n\n## Latest Vue Patterns\n- **Multiple `v-model` bindings:** `\u003CChild v-model:firstName=\"first\" v-model:lastName=\"last\">` (Vue 3.3+)\n- **`defineModel` macro:** `const modelValue = defineModel()` returns a ref that works both ways without defining prop\u002Femit.\n- **`v-bind` with `v-model`:** `\u003Cinput v-bind=\"attrs\" v-model=\"value\">` for dynamic attributes.\n\n## Interview Tip\nShow that you understand `v-model` is not magic – it's just `:value` + `@input`. Then explain how `v-model` on components uses `modelValue` and `update:modelValue`. This distinguishes junior-level knowledge.\n\n## Common Follow-up\n*\"Can you have two-way binding without `v-model`?\"* – Yes, manually: `:value=\"val\" @input=\"val = $event.target.value\"`. Also using `defineModel` in Vue 3.4+ provides a more ergonomic two-way ref.\n\n## Real-world Example\nA custom phone input component with two-way binding:\n```vue\n\u003C!-- PhoneInput.vue -->\n\u003Cscript setup>\nconst phone = defineModel() \u002F\u002F Vue 3.4+ – returns ref\n\u002F\u002F or manually: const props = defineProps(['modelValue']); const emit = defineEmits(['update:modelValue'])\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cinput \n    type=\"tel\" \n    :value=\"phone\"\n    @input=\"phone = $event.target.value\"\n    placeholder=\"123-456-7890\"\n  >\n\u003C\u002Ftemplate>\n\n\u003C!-- Parent -->\n\u003Cscript setup>\nimport { ref } from 'vue'\nconst userPhone = ref('')\n\u003C\u002Fscript>\n\u003Ctemplate>\n  \u003CPhoneInput v-model=\"userPhone\" \u002F>\n  \u003Cp>One-way display: {{ userPhone }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nVue 3's `v-model` on custom elements respects the `modelModifiers` prop. You can add modifiers like `v-model.capitalize` and handle them inside the component. The execution order: user event → modifier transforms → update variable → reactive propagation → re-render.",[45,46,47,48],"data-binding","v-model","one-way","two-way",{"id":50,"category":7,"question":51,"answer":52,"level":10,"tags":53},6,"How to handle events with v-on and event modifiers in Vue?","## Core Concept\n`v-on` (shorthand `@`) attaches event listeners to DOM elements or custom components. Event modifiers are special postfixes (`.prevent`, `.stop`, `.once`, etc.) that modify the event behavior declaratively without writing boilerplate code in JavaScript.\n\nModifiers provide common event handling patterns like preventing default, stopping propagation, capturing, passive listeners, and key\u002Fmouse combinations.\n\n## Syntax\n```vue\n\u003Cscript setup>\nconst count = ref(0)\nconst formData = ref({})\n\nfunction submitForm() {\n  console.log('submitted')\n}\n\nfunction handleClick(message) {\n  console.log(message)\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003C!-- Basic click -->\n  \u003Cbutton @click=\"count++\">Increment\u003C\u002Fbutton>\n  \n  \u003C!-- Event modifiers -->\n  \u003Cform @submit.prevent=\"submitForm\"> \u003C!-- prevents page reload -->\n  \u003Cdiv @click.stop=\"handleClick\"> \u003C!-- stops propagation -->\n  \u003Ca @click.prevent.once=\"doOnce\"> \u003C!-- prevent + only once -->\n  \u003Cdiv @scroll.passive=\"onScroll\"> \u003C!-- improves scrolling performance -->\n  \u003Cbutton @click.ctrl.exact=\"onCtrlClick\"> \u003C!-- exact Ctrl key, no other modifiers -->\n  \n  \u003C!-- Key modifiers for keyboard events -->\n  \u003Cinput @keyup.enter=\"submit\">\n  \u003Cinput @keyup.esc=\"clear\">\n  \u003Cinput @keyup.ctrl.s=\"save\"> \u003C!-- ctrl + S -->\n  \n  \u003C!-- Mouse modifiers -->\n  \u003Cdiv @click.right=\"onRightClick\"> \u003C!-- right click, same as @contextmenu -->\n  \u003Cdiv @click.middle=\"onMiddleClick\">\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. Vue compiles `@click.prevent` into a wrapper function around your handler.\n2. At runtime, when the event fires, Vue executes the wrapper which:\n   - Calls `event.preventDefault()` (for `.prevent`)\n   - Calls `event.stopPropagation()` (for `.stop`)\n   - Checks modifiers like `.ctrl`, `.shift` against `event` properties\n   - Executes your handler only if all conditions pass\n3. For `.once`, Vue attaches a listener that auto-removes after first invocation.\n4. For `.passive`, Vue sets the `{ passive: true }` option in `addEventListener`.\n\n## Reactivity Explanation\nEvent modifiers themselves don't create reactive dependencies. However, the handler functions often read or write reactive state. Vue's reactivity system tracks those reads and will re-render the component if state changes.\n\n## Practical Usage\n- **Prevent default:** Form submissions, link navigation, drag events\n- **Stop propagation:** Nested clickable elements, modal backdrops\n- **Key modifiers:** Search inputs (Enter), dialog closing (Escape), shortcuts (Ctrl+S)\n- **Once:** One-time actions like initial tour steps\n- **Passive:** Scroll events for improved performance\n\n## Interview Insight\nExplain that modifiers are **compile-time transformations** – they don't exist at runtime as separate entities. The template compiler rewrites `@click.prevent` to a function that calls `preventDefault` before your handler. This reduces runtime overhead and keeps templates clean.\n\n## Common Mistakes\n- Chaining incompatible modifiers (e.g., `.prevent` and `.passive` on same event – passive implies no `preventDefault`)\n- Forgetting that `.exact` is needed when you want only Ctrl without Shift\u002FAlt\n- Using key modifiers on non-keyboard events (won't work)\n- Assuming `.stop` stops propagation to the same element's other listeners (it does, but other listeners on same element run first)\n\n## Best Practices\n- Use modifiers instead of manually calling `preventDefault`\u002F`stopPropagation` in methods\n- Prefer `.prevent` over `event.preventDefault()` for clarity and consistency\n- Use `.once` for analytics tracking or one-time help tooltips\n- Combine modifiers in logical order (e.g., `.self.prevent` – order generally doesn't matter except when modifiers conflict)\n\n## Performance Considerations\n- `.passive` modifier can significantly improve scrolling performance on touch devices by allowing the browser to scroll immediately without waiting for handler to finish.\n- Avoid attaching many event listeners; use event delegation or custom directives if needed.\n- `.once` reduces memory by auto-removing listener after first call.\n\n## Production Recommendations\n- In production, minified modifier code is small; use them freely.\n- For complex keyboard shortcuts, consider a dedicated library (like `@vueuse\u002Fcore` `useMagicKeys`).\n- Use `.exact` for precise modifier matching to avoid accidental triggers (e.g., `Ctrl+Shift+Click` vs just `Ctrl+Click`).\n\n## Latest Vue Patterns\n- **Custom modifiers** via `defineModel` (Vue 3.4+) for `v-model`.\n- **`onClickOutside`** composable from VueUse is often easier than manual `@click` with `stopPropagation`.\n- **`@vue\u002Fruntime-dom`** includes all standard DOM event modifiers.\n\n## Interview Tip\nBe ready to explain the difference between `.prevent` and `.stop`, and when you'd use both. Also mention that `.native` is removed in Vue 3 – now you `emits` declaration determines component events vs native listeners.\n\n## Common Follow-up\n*\"How do you listen to custom events from child components?\"* – Use `@custom-event=\"handler\"` without modifiers (modifiers are for DOM events only). The child calls `emit('custom-event')`.\n\n## Real-world Example\nA modal that closes on Escape, stops propagation, and prevents body scroll:\n```vue\n\u003Ctemplate>\n  \u003Cdiv \n    v-if=\"isOpen\" \n    class=\"modal-backdrop\" \n    @click.self=\"closeModal\"\n    @keyup.esc=\"closeModal\"\n  >\n    \u003Cdiv class=\"modal-content\">\n      \u003Cbutton @click.stop=\"closeModal\">X\u003C\u002Fbutton>\n      \u003Cform @submit.prevent=\"handleSave\">\n        \u003Cinput v-model=\"title\" @keyup.enter.prevent=\"handleSave\">\n        \u003Cbutton type=\"submit\">Save\u003C\u002Fbutton>\n      \u003C\u002Fform>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nconst isOpen = ref(true)\nconst closeModal = () => { isOpen.value = false }\nconst handleSave = () => { \u002F* save logic *\u002F closeModal() }\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\nVue also supports **modifier keys** like `.exact` and combination chaining: `@click.ctrl.alt.shift.exact`. The order of key modifiers doesn't matter. For system modifiers (Ctrl, Alt, Shift, Meta), they check that the key is pressed. `.exact` ensures no other modifier keys are pressed. You can also create custom key aliases via `config.keyCodes` (deprecated) – use global key names instead.",[38,37,54,55],"modifiers","event-handling",{"id":57,"category":7,"question":58,"answer":59,"level":10,"tags":60},7,"Explain v-if vs v-show vs v-else: differences and use cases.","## Core Concept\n- **`v-if`**: Conditionally renders the element. If the condition is falsy, the element is **completely destroyed** and removed from the DOM. Re-creating when condition becomes truthy.\n- **`v-show`**: Always renders the element in the DOM but toggles its visibility using CSS `display: none` (or `display: block`\u002Fflex\u002Fetc when visible).\n- **`v-else` \u002F `v-else-if`**: Must follow `v-if` or `v-else-if` blocks, providing else branches without extra nesting.\n\n**Key difference**: `v-if` is \"real\" conditional rendering (lazy, toggles cost), `v-show` is CSS-based (always in DOM, cheap toggles).\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { ref } from 'vue'\nconst isLoggedIn = ref(false)\nconst userRole = ref('guest')\nconst showSidebar = ref(true)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003C!-- v-if with v-else -->\n  \u003Cdiv v-if=\"isLoggedIn\">Welcome back!\u003C\u002Fdiv>\n  \u003Cdiv v-else>Please log in\u003C\u002Fdiv>\n  \n  \u003C!-- v-else-if chain -->\n  \u003Cdiv v-if=\"userRole === 'admin'\">Admin Panel\u003C\u002Fdiv>\n  \u003Cdiv v-else-if=\"userRole === 'editor'\">Editor Dashboard\u003C\u002Fdiv>\n  \u003Cdiv v-else>Guest View\u003C\u002Fdiv>\n  \n  \u003C!-- v-show toggles visibility -->\n  \u003Cdiv v-show=\"showSidebar\">\n    \u003Cp>Sidebar content (always in DOM)\u003C\u002Fp>\n  \u003C\u002Fdiv>\n  \n  \u003C!-- template tag with v-if (no wrapper) -->\n  \u003Ctemplate v-if=\"isLoggedIn\">\n    \u003Ch1>Dashboard\u003C\u002Fh1>\n    \u003Cp>Your stats\u003C\u002Fp>\n  \u003C\u002Ftemplate>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n**v-if:**\n1. During initial render, if condition is false, Vue **does not create** the vnode or DOM elements.\n2. When condition becomes true, Vue creates the component\u002Felement, inserts it into DOM, and runs lifecycle hooks (if component: `onMounted`).\n3. When condition becomes false, Vue destroys the vnode, removes DOM, and calls `onUnmounted`.\n\n**v-show:**\n1. Element is always created and mounted once.\n2. On toggle, Vue just updates `element.style.display`.\n3. No destroy\u002Frecreate, so child component lifecycles run only once.\n\n## Reactivity Explanation\nBoth directives react to changes in the condition expression. `v-if` triggers a full component lifecycle (create\u002Fdestroy) based on reactive condition; `v-show` triggers a style update. The reactivity system tracks the condition variable and schedules a re-render, during which the directive logic runs.\n\n## Practical Usage\n- **`v-if`**: Rarely toggled elements (e.g., modal after confirm, error message that appears once), conditional routing, lazy loading heavy components\n- **`v-show`**: Frequently toggled UI (accordion, tab panels, dropdown menus, tooltips), elements with expensive initial render but cheap toggling\n- **`v-else`\u002F`v-else-if`**: Login\u002Flogout states, multi-step forms, permission-based UI\n\n## Interview Insight\nExplain the **lifecycle difference** – `v-if` destroys and recreates components, so `onMounted` and `onUnmounted` fire each toggle. `v-show` does not. Also mention that `v-if` is lazy – if initially false, the component never initializes until needed.\n\n## Common Mistakes\n- Using `v-if` on frequently toggled elements (causes performance issues due to constant destroy\u002Frecreate)\n- Using `v-show` on elements with heavy initial render but hidden (still renders even if invisible, wasting resources)\n- Putting `v-else` without immediately preceding `v-if` or `v-else-if` (will not work)\n- Using `v-show` on `\u003Ctemplate>` (not allowed – `v-show` only works on single elements)\n\n## Best Practices\n- Default to `v-if` unless toggling very frequently (more than a few times per minute)\n- Use `v-show` for components that toggle visibility often and are cheap to render initially\n- Group conditions with `\u003Ctemplate>` to avoid extra divs\n- Use `v-else-if` for more than two mutually exclusive conditions\n\n## Performance Considerations\n- **Initial render cost:** `v-if` is cheaper if condition is false (doesn't render at all); `v-show` always renders regardless of visibility\n- **Toggle cost:** `v-if` is expensive (DOM insertion\u002Fdeletion, lifecycle) while `v-show` is cheap (just CSS change)\n- **Memory:** `v-if` for false branch frees memory; `v-show` keeps everything in DOM\n- **Heavy components:** Use `v-if` + `\u003CKeepAlive>` if you need to preserve state but avoid re-render cost\n\n## Production Recommendations\n- For tab interfaces with many tabs, use `v-show` on tab content if switching is frequent and content is medium-weight.\n- For modals and dialogs, use `v-if` because they rarely open and you want to reset state when closed.\n- Use `v-if` with `key` attribute to force full re-render even for same component type.\n- In lists with conditional items, prefer `v-show` on each item if the filter changes often.\n\n## Latest Vue Patterns\n- Vue 3's `\u003CSuspense>` works best with `v-if` for async components.\n- `v-memo` can be combined with `v-if` to memoize conditional subtrees.\n- `defineModel` doesn't directly affect `v-if`\u002F`v-show`, but you can conditionally bind models.\n\n## Interview Tip\nMany candidates know the difference but fail to mention the **`\u003Ctemplate>` support** – `v-if` works on `\u003Ctemplate>` (invisible wrapper), `v-show` does not. This is a common interview trick.\n\n## Common Follow-up\n*\"Can you use `v-else` with `v-show`?\"* – No. `v-else` only works with `v-if`\u002F`v-else-if`. For mutually exclusive `v-show`, use explicit condition logic or computed properties.\n\n## Real-world Example\nA settings panel with tabs (frequent toggle) and a confirmation modal (rare):\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003C!-- Tab content: frequent toggles -->\n    \u003Cdiv v-show=\"activeTab === 'profile'\">Profile settings...\u003C\u002Fdiv>\n    \u003Cdiv v-show=\"activeTab === 'security'\">Security settings...\u003C\u002Fdiv>\n    \n    \u003C!-- Modal: shown rarely, resets state each time -->\n    \u003Cdiv v-if=\"showConfirmModal\" class=\"modal\">\n      \u003Cp>Are you sure?\u003C\u002Fp>\n      \u003Cbutton @click=\"confirm\">Yes\u003C\u002Fbutton>\n      \u003Cbutton @click=\"showConfirmModal = false\">No\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nVue's compiler optimizes `v-if` by hoisting stable parts outside the conditional block. For `v-show`, the element is always part of the template’s static tree. In extremely performance-critical scenarios (thousands of toggles per second), `v-show`'s style updates can be slightly faster, but both are generally fast enough. The true cost difference is in component initialization\u002Fdestruction, not DOM property updates.",[61,62,63,29],"conditional-rendering","v-if","v-show",{"id":65,"category":7,"question":66,"answer":67,"level":10,"tags":68},8,"How to use v-for for list rendering and why is the key attribute important?","## Core Concept\n`v-for` renders a list of items by iterating over an array, object, or range. The `key` attribute provides a unique identity for each rendered node, enabling Vue to efficiently patch the DOM when the list changes (reordering, adding, removing).\n\nWithout `key`, Vue uses an **in-place patch strategy** that reuses elements and may cause state bugs, incorrect animations, and poor performance.\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { ref } from 'vue'\nconst items = ref([{ id: 1, text: 'Apple' }, { id: 2, text: 'Banana' }])\nconst obj = ref({ a: 'A', b: 'B' })\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003C!-- Array iteration -->\n  \u003Cli v-for=\"item in items\" :key=\"item.id\">\n    {{ item.text }}\n  \u003C\u002Fli>\n  \n  \u003C!-- With index -->\n  \u003Cli v-for=\"(item, index) in items\" :key=\"item.id\">\n    {{ index }} - {{ item.text }}\n  \u003C\u002Fli>\n  \n  \u003C!-- Object iteration -->\n  \u003Cli v-for=\"(value, key, index) in obj\" :key=\"key\">\n    {{ key }}: {{ value }}\n  \u003C\u002Fli>\n  \n  \u003C!-- Range (1 to 10) -->\n  \u003Cspan v-for=\"n in 10\" :key=\"n\">{{ n }}\u003C\u002Fspan>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. Vue evaluates the expression (e.g., `items` array) and gets the new list.\n2. Compares new list with previous virtual DOM nodes using `key` values.\n3. Performs **three operations**:\n   - **Reordering**: Moves existing nodes to correct positions without re-rendering content.\n   - **Addition**: Creates new nodes for new items.\n   - **Removal**: Destroys nodes for removed items.\n4. Applies minimal DOM mutations based on diff result.\n\n## Reactivity Explanation\n`v-for` re-renders when the source array mutates (via `push`, `pop`, `splice`, etc.) or when the array reference changes. Vue wraps array mutation methods to trigger updates. With `key`, Vue tracks each node's identity; without it, Vue cannot tell if an element moved, so it updates content in place, which may break component state.\n\n## Practical Usage\n- Rendering product lists, tables, dropdown options\n- Generating dynamic forms from schema\n- Chat message lists, comment threads\n- Navigation menus from routes array\n\n## Interview Insight\nEmphasize that `key` is **not optional for lists with dynamic order** – it's required for correctness. Explain that `key` should be **stable, unique, and primitive** (string\u002Fnumber). Using `index` as key is an anti-pattern when list can reorder.\n\n## Common Mistakes\n- Using `index` as key for lists that can reorder, filter, or sort (causes state bugs)\n- Forgetting `:key` altogether (Vue warns in dev, but still works with degraded performance)\n- Using non-primitive keys (objects) – Vue uses strict equality `===`, so different objects with same content fail\n- Using `v-for` and `v-if` on same element (v-if runs first, can cause errors; use computed or wrapper)\n\n## Best Practices\n- Always use `:key` with `v-for`\n- Use unique ID from data (database ID, UUID) as key\n- For temporary lists, use `nanoid` or `Symbol()` but ensure stability across renders\n- Prefer `Map` or object lookup for large lists instead of `v-for` with nested loops\n- Use `\u003Ctemplate v-for>` for multiple elements without wrapper\n\n## Performance Considerations\n- Proper `key` allows O(n) diffing instead of O(n²) for reorderable lists\n- Without keys, Vue may unmount and remount components unnecessarily, losing state\n- Huge lists (> 2000 items) should use virtualization (`vue-virtual-scroller`)\n- Avoid complex expressions inside `v-for` – compute outside or use computed\n\n## Production Recommendations\n- For static lists (never change), you can omit `key` but still add for clarity\n- When fetching paginated data, use `key` as `item.id` plus page number to reset internal state\n- For animated list transitions, stable keys are mandatory for correct enter\u002Fleave animations\n- Use `shallowRef` for large arrays to reduce deep reactivity overhead\n\n## Latest Vue Patterns\n- `v-for` with `Map` and `Set` in Vue 3 (iterates over values)\n- `v-memo` for memoizing `v-for` subtrees (Vue 3.2+)\n- In Vue 3, `v-for` precedence is lower than `v-if` (different from Vue 2)\n\n## Interview Tip\nDemonstrate understanding of **diffing algorithm** with keys: Vue uses `sameVnode` check – if keys match and element type matches, node is reused; if not, full replacement. Without keys, Vue assumes same type = same node, causing content overwrites.\n\n## Common Follow-up\n*\"What happens if keys are not unique?\"* – Vue will reuse nodes incorrectly, leading to DOM mismatches, duplicated elements, and broken component state. In development, Vue warns. In production, behavior is undefined.\n\n## Real-world Example\nTodo list with reorder and filter:\n```vue\n\u003Ctemplate>\n  \u003Cinput v-model=\"newTodo\" @keyup.enter=\"addTodo\">\n  \u003Cbutton @click=\"sortTodos\">Sort A-Z\u003C\u002Fbutton>\n  \n  \u003Cdiv v-for=\"todo in filteredTodos\" :key=\"todo.id\">\n    \u003Cinput type=\"checkbox\" v-model=\"todo.completed\">\n    \u003Cspan :class=\"{ done: todo.completed }\">{{ todo.text }}\u003C\u002Fspan>\n    \u003Cbutton @click=\"removeTodo(todo.id)\">X\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { ref, computed } from 'vue'\nlet nextId = 1\nconst todos = ref([{ id: nextId++, text: 'Learn Vue', completed: false }])\nconst newTodo = ref('')\nconst filter = ref('all')\n\nconst filteredTodos = computed(() => {\n  if (filter.value === 'active') return todos.value.filter(t => !t.completed)\n  if (filter.value === 'done') return todos.value.filter(t => t.completed)\n  return todos.value\n})\n\nfunction addTodo() {\n  todos.value.push({ id: nextId++, text: newTodo.value, completed: false })\n  newTodo.value = ''\n}\n\nfunction sortTodos() {\n  todos.value.sort((a, b) => a.text.localeCompare(b.text))\n}\n\nfunction removeTodo(id) {\n  todos.value = todos.value.filter(t => t.id !== id)\n}\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\nVue's `v-for` keying is inspired by React's list diffing. Under the hood, Vue uses `patchKeyedChildren` algorithm that does: \n1. Sync from start (common prefix)\n2. Sync from end (common suffix)\n3. Handle unmounts\u002Fmounts with key map\n4. Longest increasing subsequence optimization for minimal moves\nThis makes keyed diff O(n) in typical cases. Without keys, Vue falls back to `patchUnkeyedChildren` (simple loop, O(n) but cannot reorder, leading to many updates).",[69,70,71,72],"list-rendering","v-for","key","diffing",{"id":74,"category":7,"question":75,"answer":76,"level":10,"tags":77},9,"What are computed properties and how do they differ from methods and watch?","## Core Concept\n**Computed properties** are cached values that automatically recalculate when their reactive dependencies change. They are **getter functions** that Vue treats as read-only reactive values.\n\n**Methods** are functions that execute on every render or call, without caching. **Watch** is for side effects when data changes, not for deriving values.\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { ref, computed, watch } from 'vue'\nconst firstName = ref('John')\nconst lastName = ref('Doe')\nconst count = ref(0)\n\n\u002F\u002F Computed property (cached)\nconst fullName = computed(() => `${firstName.value} ${lastName.value}`)\n\n\u002F\u002F Method (re-executes on every render)\nfunction getFullName() {\n  return `${firstName.value} ${lastName.value}`\n}\n\n\u002F\u002F Watcher (side effects)\nwatch(fullName, (newName, oldName) => {\n  console.log(`Name changed from ${oldName} to ${newName}`)\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cp>Computed: {{ fullName }}\u003C\u002Fp>  \u003C!-- cached, re-evaluates only when firstName\u002FlastName change -->\n  \u003Cp>Method: {{ getFullName() }}\u003C\u002Fp> \u003C!-- re-evaluates on every re-render -->\n  \u003Cbutton @click=\"count++\">Count: {{ count }}\u003C\u002Fbutton>\n  \u003C!-- Even clicking count (unrelated to names) causes method to re-run, but not computed -->\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n**Computed:**\n1. During render, Vue reads `fullName.value` (computed ref).\n2. Computed runs its getter, tracks dependencies (`firstName`, `lastName`).\n3. Caches the result.\n4. When dependencies change, computed marks dirty; next read re-executes getter.\n\n**Method:**\n1. In template, `getFullName()` is called on every render (no caching).\n2. Re-runs even if dependencies unchanged.\n\n**Watch:**\n1. Runs immediately or lazily (default lazy).\n2. When watched source changes, executes callback – not used in template.\n\n## Reactivity Explanation\nComputed properties create a **reactive effect** that tracks dependencies. When any dependency changes, the computed effect re-runs but only notifies consumers (like template) when the actual value changes. Vue can skip re-rendering if computed result hasn't changed.\n\n## Practical Usage\n- **Computed:** Formatting data (date, currency), filtering\u002Fsorting lists, deriving state from other state, validating forms\n- **Methods:** Event handlers, callbacks, complex logic that shouldn't be cached\n- **Watch:** Saving data to localStorage, API calls on change, complex side effects, performing async operations\n\n## Interview Insight\nHighlight the **caching mechanism** – computed only re-evaluates when dependencies change. This is critical for expensive operations (e.g., sorting large arrays). Methods always re-run, potentially causing performance issues.\n\n## Common Mistakes\n- Mutating computed value directly (computed is read-only unless using setter)\n- Using computed for side effects (computed should be pure)\n- Using watch when computed would suffice (watch is for side effects, not deriving values)\n- Putting heavy async operations in computed (computed must be synchronous)\n\n## Best Practices\n- Default to computed for any derived reactive state\n- Use methods for event handlers and explicit user actions\n- Use watch only for side effects that don't produce a value\n- Prefer computed over `v-for` with filter in template\n- For expensive computed, consider `computed({ get, set })` for two-way binding\n\n## Performance Considerations\n- Computed caches results, preventing wasted recalculations\n- Avoid creating new arrays\u002Fobjects in computed getter unless necessary (triggers re-render even if content same)\n- For large lists, computed with `.filter()` is fine but consider using `shallowRef` for output\n- `watch` with `deep: true` is expensive on large objects – prefer watching specific paths\n\n## Production Recommendations\n- Use computed for derived state in Pinia getters as well\n- For computed that depend on async data, combine with `ref` and `watchEffect`\n- In performance-critical components, memoize computed results that return objects\n- Use `computed` with `{ shallow: true }` (Vue 3.4+) for shallow ref caching\n\n## Latest Vue Patterns\n- **Writable computed:** `const fullName = computed({ get: () => ..., set: (val) => ... })`\n- **`toValue`** utility to unwrap refs in computed dependencies\n- **`computed` with `maybeRef`** – can accept ref or plain value\n\n## Interview Tip\nExplain the **reactive dependency graph** – computed forms a node in the graph. When a dependency updates, the computed node is marked dirty but doesn't re-evaluate until read. This lazy evaluation improves performance.\n\n## Common Follow-up\n*\"When would you use watch instead of computed?\"* – Watch is for side effects: API calls, DOM manipulations, routing, logging, or any operation that doesn't return a value to the template. Computed should be pure and synchronous.\n\n## Real-world Example\nShopping cart with computed totals:\n```vue\n\u003Cscript setup>\nimport { ref, computed } from 'vue'\nconst cart = ref([\n  { id: 1, name: 'Shirt', price: 25, quantity: 2 },\n  { id: 2, name: 'Shoes', price: 80, quantity: 1 }\n])\n\n\u002F\u002F Computed: derived from cart\nconst subtotal = computed(() => \n  cart.value.reduce((sum, item) => sum + item.price * item.quantity, 0)\n)\nconst tax = computed(() => subtotal.value * 0.1)\nconst total = computed(() => subtotal.value + tax.value)\n\n\u002F\u002F Computed with getter\u002Fsetter for discount code\nconst discount = ref(0)\nconst discountCode = computed({\n  get: () => discount.value ? 'SAVE10' : '',\n  set: (code) => {\n    if (code === 'SAVE10') discount.value = subtotal.value * 0.1\n    else discount.value = 0\n  }\n})\n\n\u002F\u002F Method: handle checkout (side effect)\nfunction checkout() {\n  console.log(`Total: ${total.value}`)\n}\n\n\u002F\u002F Watch: save cart to localStorage\nwatch(cart, (newCart) => {\n  localStorage.setItem('cart', JSON.stringify(newCart))\n}, { deep: true })\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv v-for=\"item in cart\" :key=\"item.id\">\n    {{ item.name }} x {{ item.quantity }} = ${{ item.price * item.quantity }}\n  \u003C\u002Fdiv>\n  \u003Cp>Subtotal: ${{ subtotal }}\u003C\u002Fp>\n  \u003Cp>Tax (10%): ${{ tax }}\u003C\u002Fp>\n  \u003Cp>Total: ${{ total }}\u003C\u002Fp>\n  \u003Cinput v-model=\"discountCode\" placeholder=\"Discount code\">\n  \u003Cbutton @click=\"checkout\">Checkout\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nComputed properties are implemented using the `ComputedRefImpl` class. When a computed is read, it checks a `_dirty` flag. If dirty, it re-runs the getter, updates the cached value, and clears dirty. This is why dependencies can change many times but computed only recomputes once before being read again. In contrast, `watchEffect` runs immediately and eagerly on dependency change – different use cases.",[78,79,80,81],"computed","methods","watch","reactivity",{"id":83,"category":7,"question":84,"answer":85,"level":10,"tags":86},10,"Explain component basics: props, emits, and slots.","## Core Concept\n**Props** allow parent components to pass data down to child components (one-way flow). **Emits** allow child components to send events up to parents. **Slots** allow parents to inject template content into child components (content projection).\n\nThese three mechanisms form the foundation of Vue's component communication and composition.\n\n## Syntax\n```vue\n\u003C!-- ChildComponent.vue -->\n\u003Cscript setup>\n\u002F\u002F Props definition\nconst props = defineProps({\n  title: String,\n  count: { type: Number, default: 0 },\n  user: { type: Object, required: true }\n})\n\n\u002F\u002F Emits definition\nconst emit = defineEmits(['update', 'delete'])\n\nfunction handleClick() {\n  emit('update', props.count + 1)\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Ch3>{{ title }}\u003C\u002Fh3>\n    \u003Cp>Count: {{ count }}\u003C\u002Fp>\n    \u003Cbutton @click=\"handleClick\">Increment\u003C\u002Fbutton>\n    \u003Cbutton @click=\"emit('delete')\">Delete\u003C\u002Fbutton>\n    \n    \u003C!-- Slots: named and default -->\n    \u003Cdiv class=\"header\">\n      \u003Cslot name=\"header\">Default header\u003C\u002Fslot>\n    \u003C\u002Fdiv>\n    \u003Cdiv class=\"content\">\n      \u003Cslot>Default content\u003C\u002Fslot>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n```vue\n\u003C!-- ParentComponent.vue -->\n\u003Cscript setup>\nimport ChildComponent from '.\u002FChildComponent.vue'\nimport { ref } from 'vue'\n\nconst parentCount = ref(5)\nconst user = { name: 'Alice' }\n\nfunction handleUpdate(newCount) {\n  parentCount.value = newCount\n}\n\nfunction handleDelete() {\n  console.log('Deleted')\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CChildComponent \n    title=\"My Child\"\n    :count=\"parentCount\"\n    :user=\"user\"\n    @update=\"handleUpdate\"\n    @delete=\"handleDelete\"\n  >\n    \u003Ctemplate #header>\n      \u003Ch1>Custom Header\u003C\u002Fh1>\n    \u003C\u002Ftemplate>\n    \u003Ctemplate #default>\n      \u003Cp>This is custom content\u003C\u002Fp>\n    \u003C\u002Ftemplate>\n  \u003C\u002FChildComponent>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. **Props:** Parent renders → passes props to child → child receives props as reactive refs (in `\u003Cscript setup>`) → child re-renders when props change.\n2. **Emits:** Child calls `emit('event', data)` → Vue creates a custom event → parent's `@event` handler receives data → parent updates its state → re-renders parent and child.\n3. **Slots:** Parent compiles slot content in parent's scope → passes VNodes to child → child renders slots in its template positions (scoped slots allow child to pass data back to slot content).\n\n## Reactivity Explanation\nProps are **shallow reactive** – Vue tracks property access for re-renders but does not deep watch unless `deep: true` in watch. Emits trigger parent reactivity via explicit state updates. Slots are reactive if the slot content uses reactive data from parent scope.\n\n## Practical Usage\n- **Props:** Configuration, data passing, dependency injection for simple hierarchies\n- **Emits:** User actions, form submissions, internal state changes needing parent sync\n- **Slots:** Layout components (cards, modals), renderless components, component customization\n\n## Interview Insight\nEmphasize **one-way data flow** – props down, events up. Slots are often underutilized; they provide powerful inversion of control. In Vue 3, `v-model` on components is syntactic sugar for `:modelValue` prop + `@update:modelValue` emit.\n\n## Common Mistakes\n- Mutating props directly in child (causes warning and breaks reactivity)\n- Forgetting to define emits (Vue 3 requires `defineEmits` for proper event handling, though works without but loses validation)\n- Using slot default content incorrectly (default content shows only if slot empty)\n- Overusing props drilling (use `provide\u002Finject` for deep hierarchies)\n\n## Best Practices\n- Use `defineProps` with validation (type, required, default, validator)\n- Use `defineEmits` with validation (array or object with validator functions)\n- Prefer kebab-case for emit event names in templates but camelCase in JS\n- Use scoped slots for data-driven renderless components\n- Destructure props with `toRefs` if passing to composables\n\n## Performance Considerations\n- Props are cheap; thousands of props updates fine\n- Emits trigger parent re-renders; avoid excessive emits in loops\n- Slots are compiled per parent; dynamic slot names cause re-renders\n- Use `v-once` on static slots to prevent re-renders\n\n## Production Recommendations\n- For component libraries, provide comprehensive prop validation and emit types\n- Use TypeScript with `defineProps\u003CType>()` and `defineEmits\u003CType>()` for type safety\n- Prefer scoped slots over render props pattern (Vue-specific)\n- Use `v-slot` shorthand `#` for named slots\n\n## Latest Vue Patterns\n- **`defineModel`** (Vue 3.4+) replaces manual `modelValue` prop + emit\n- **Generic components** using `defineProps\u003C{ item: T }>()` with `defineGeneric`\n- **Slots with types** – `defineSlots\u003C{ default(props: { msg: string }): any }>()`\n\n## Interview Tip\nExplain that **slots are compiled in the parent scope** – they have access to parent data, not child data, unless using scoped slots which pass child data up.\n\n## Common Follow-up\n*\"What's the difference between props and `provide\u002Finject`?\"* – Props are explicit and reactive for direct parent-child; provide\u002Finject is for deep ancestors\u002Fdescendants, implicit, and can be reactive if providing a ref.\n\n## Real-world Example\nData table component with customizable columns:\n```vue\n\u003C!-- DataTable.vue -->\n\u003Cscript setup>\nconst props = defineProps({\n  items: Array,\n  columns: Array\n})\nconst emit = defineEmits(['row-click'])\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Ctable>\n    \u003Cthead>\n      \u003Ctr>\u003Cth v-for=\"col in columns\" :key=\"col.key\">{{ col.label }}\u003C\u002Fth>\u003C\u002Ftr>\n    \u003C\u002Fthead>\n    \u003Ctbody>\n      \u003Ctr v-for=\"item in items\" :key=\"item.id\" @click=\"emit('row-click', item)\">\n        \u003Ctd v-for=\"col in columns\" :key=\"col.key\">\n          \u003C!-- Scoped slot for custom column rendering -->\n          \u003Cslot :name=\"`col-${col.key}`\" :item=\"item\" :value=\"item[col.key]\">\n            {{ item[col.key] }}\n          \u003C\u002Fslot>\n        \u003C\u002Ftd>\n      \u003C\u002Ftr>\n    \u003C\u002Ftbody>\n  \u003C\u002Ftable>\n\u003C\u002Ftemplate>\n\n\u003C!-- Usage -->\n\u003CDataTable :items=\"users\" :columns=\"columns\" @row-click=\"handleRowClick\">\n  \u003Ctemplate #col-status=\"{ item }\">\n    \u003Cspan :class=\"item.active ? 'active' : 'inactive'\">\n      {{ item.active ? 'Active' : 'Inactive' }}\n    \u003C\u002Fspan>\n  \u003C\u002Ftemplate>\n  \u003Ctemplate #col-actions=\"{ item }\">\n    \u003Cbutton @click.stop=\"editUser(item)\">Edit\u003C\u002Fbutton>\n  \u003C\u002Ftemplate>\n\u003C\u002FDataTable>\n```\n\n## Advanced Notes\nProps are validated at runtime in development. Emits validation can check event payload shape. Slots are **VNodes** – they can be stored in refs and even passed programmatically (advanced render functions). Vue 3's `useSlots()` and `useAttrs()` give access to slots and fallthrough attributes.",[87,88,89,90,91],"components","props","emits","slots","communication",{"id":93,"category":94,"question":95,"answer":96,"level":10,"tags":97},11,"Lifecycle","What are the Vue component lifecycle hooks and their execution order?","## Core Concept\nLifecycle hooks are functions that allow you to run code at specific stages of a component's existence: creation, mounting, updating, and unmounting. In Vue 3 Composition API, they are imported functions prefixed with `on` (e.g., `onMounted`).\n\n**Execution order:**\n1. `setup()` – not a hook but runs first (before any hooks)\n2. `onBeforeMount()` – before DOM is rendered\n3. `onMounted()` – component added to DOM\n4. `onBeforeUpdate()` – before reactive data changes the DOM\n5. `onUpdated()` – after DOM re-render\n6. `onBeforeUnmount()` – before component is removed\n7. `onUnmounted()` – after removal\n8. `onErrorCaptured()` – when an error propagates from a descendant\n9. `onActivated()` \u002F `onDeactivated()` – for `\u003CKeepAlive>`\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, ref } from 'vue'\n\nconst count = ref(0)\n\nonBeforeMount(() => console.log('Before mount – no DOM yet'))\nonMounted(() => console.log('Mounted – DOM ready'))\nonBeforeUpdate(() => console.log('Before update – count will change'))\nonUpdated(() => console.log('Updated – DOM patched'))\nonBeforeUnmount(() => console.log('Before unmount – cleanup time'))\nonUnmounted(() => console.log('Unmounted – component gone'))\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cbutton @click=\"count++\">{{ count }}\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. Component instance created, `setup()` runs (reactive state initialised).\n2. `onBeforeMount` – template compiled, virtual DOM created, not yet inserted.\n3. `onMounted` – real DOM appended; safe to access `ref` elements or run DOM libraries.\n4. When reactive state changes, `onBeforeUpdate` triggers, then Vue re-renders, then `onUpdated`.\n5. When component is removed (e.g., `v-if` false), `onBeforeUnmount` then `onUnmounted`.\n\n## Reactivity Explanation\nLifecycle hooks themselves are not reactive, but they observe the component's reactive lifecycle. Vue schedules these hook calls as part of its internal state machine.\n\n## Practical Usage\n- `onMounted`: Fetch initial data, set up event listeners, access DOM elements.\n- `onBeforeUnmount`: Clean up timers, remove event listeners, cancel requests.\n- `onErrorCaptured`: Log errors or show fallback UI.\n\n## Interview Insight\nIn Vue 3 Composition API, lifecycle hooks can be called multiple times inside a single component (e.g., different composables). They are scoped to the component instance and automatically cleaned up.\n\n## Common Mistakes\n- Using `onMounted` to update state that triggers another render (fine, but be aware of extra render).\n- Forgetting to clean up global listeners in `onBeforeUnmount` (causes memory leaks).\n- Accessing DOM elements in `onBeforeMount` (they don't exist yet).\n\n## Best Practices\n- Use `onMounted` for API calls (not `setup()` because SSR compatibility).\n- Keep hooks focused – extract logic into composables.\n- Use `onActivated` \u002F `onDeactivated` for cached components.\n\n## Performance Considerations\n- `onUpdated` runs after every re-render; avoid heavy computations here.\n- Use `onBeforeUnmount` to prevent dangling subscriptions.\n\n## Production Recommendations\n- For async data, combine `onMounted` with loading\u002Ferror states.\n- In SSR, `onMounted` only runs on client – safe for browser APIs.\n\n## Latest Vue Patterns\n- `onServerPrefetch` for SSR data fetching.\n- `onWatcherCleanup` (Vue 3.5+) for async watcher cancellation.\n\n## Interview Tip\nMemorise the order: **BeforeMount → Mounted → BeforeUpdate → Updated → BeforeUnmount → Unmounted**. Interviewers often ask which hook to use for API calls – answer `onMounted`.\n\n## Common Follow-up\n*\"What is the difference between `created` (Vue 2) and `setup()` (Vue 3)?\"* – `setup()` runs before `onBeforeMount`, replacing `created`. `onMounted` replaces `mounted`.\n\n## Real-world Example\n```vue\n\u003Cscript setup>\nimport { ref, onMounted, onBeforeUnmount } from 'vue'\nconst mouseX = ref(0)\nconst mouseY = ref(0)\n\nfunction updateMouse(e) {\n  mouseX.value = e.clientX\n  mouseY.value = e.clientY\n}\n\nonMounted(() => window.addEventListener('mousemove', updateMouse))\nonBeforeUnmount(() => window.removeEventListener('mousemove', updateMouse))\n\u003C\u002Fscript>\n\n\u003Ctemplate>Mouse: {{ mouseX }}, {{ mouseY }}\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nVue's scheduler batches lifecycle hooks. For example, multiple reactive updates in one tick trigger only one `onBeforeUpdate` and `onUpdated`. You can use `nextTick()` to wait after `onUpdated` for DOM stability.",[98,99,100,101],"lifecycle","hooks","mounted","unmounted",{"id":103,"category":104,"question":105,"answer":106,"level":10,"tags":107},12,"Forms","How to handle form inputs with v-model in Vue? (text, checkbox, radio, select)","## Core Concept\n`v-model` creates two-way bindings on form input, textarea, and select elements. It automatically picks the correct way to update the element based on the input type – `value` + `input` for text inputs, `checked` + `change` for checkboxes\u002Fradios, and `value` + `change` for selects.\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { ref } from 'vue'\n\n\u002F\u002F Text inputs\nconst text = ref('')\nconst email = ref('')\n\n\u002F\u002F Checkbox (single, boolean)\nconst agreed = ref(false)\n\n\u002F\u002F Checkbox (multiple, array)\nconst hobbies = ref([])\n\n\u002F\u002F Radio buttons\nconst selectedColor = ref('red')\n\n\u002F\u002F Select (single)\nconst selectedCity = ref('')\n\n\u002F\u002F Select (multiple)\nconst selectedCities = ref([])\n\n\u002F\u002F Textarea\nconst message = ref('')\n\n\u002F\u002F Modifiers\nconst trimmedText = ref('')\nconst numberAge = ref(null)\nconst lazyText = ref('')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003C!-- Text \u002F email \u002F password -->\n  \u003Cinput v-model=\"text\" type=\"text\">\n  \u003Cinput v-model=\"email\" type=\"email\">\n\n  \u003C!-- Single checkbox -> boolean -->\n  \u003Cinput type=\"checkbox\" v-model=\"agreed\"> I agree\n\n  \u003C!-- Multiple checkboxes -> array -->\n  \u003Cinput type=\"checkbox\" value=\"reading\" v-model=\"hobbies\"> Reading\n  \u003Cinput type=\"checkbox\" value=\"gaming\" v-model=\"hobbies\"> Gaming\n\n  \u003C!-- Radio -> string of selected value -->\n  \u003Cinput type=\"radio\" value=\"red\" v-model=\"selectedColor\"> Red\n  \u003Cinput type=\"radio\" value=\"blue\" v-model=\"selectedColor\"> Blue\n\n  \u003C!-- Select single -->\n  \u003Cselect v-model=\"selectedCity\">\n    \u003Coption value=\"nyc\">New York\u003C\u002Foption>\n    \u003Coption value=\"london\">London\u003C\u002Foption>\n  \u003C\u002Fselect>\n\n  \u003C!-- Select multiple -->\n  \u003Cselect v-model=\"selectedCities\" multiple>\n    \u003Coption value=\"nyc\">NYC\u003C\u002Foption>\n    \u003Coption value=\"london\">London\u003C\u002Foption>\n  \u003C\u002Fselect>\n\n  \u003C!-- Textarea -->\n  \u003Ctextarea v-model=\"message\">\u003C\u002Ftextarea>\n\n  \u003C!-- Modifiers -->\n  \u003Cinput v-model.trim=\"trimmedText\">          \u003C!-- Remove whitespace -->\n  \u003Cinput v-model.number=\"numberAge\" type=\"number\"> \u003C!-- Parse to number -->\n  \u003Cinput v-model.lazy=\"lazyText\">            \u003C!-- Sync on change, not input -->\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. Vue creates a binding based on element type and modifiers.\n2. On initial render, sets DOM value\u002Fchecked from bound variable.\n3. On user input, Vue updates the variable, which triggers reactivity.\n4. The reactive update re-renders the input (usually unnecessary but safe).\n\n## Reactivity Explanation\n`v-model` is syntactic sugar: `\u003Cinput :value=\"text\" @input=\"text = $event.target.value\">`. For checkboxes: `:checked` + `@change`. For components: `:modelValue` + `@update:modelValue`. The bound variable must be a ref (or reactive property) so that assignment triggers reactivity.\n\n## Practical Usage\n- Login\u002Fregistration forms\n- Filter controls (search, price range)\n- Preference panels (checkboxes, toggles)\n- Multi-step wizards\n\n## Interview Insight\nExplain that `v-model` on custom components is not automatic – the component must accept a `modelValue` prop and emit `update:modelValue`. Vue 3.4+ `defineModel` macro simplifies this.\n\n## Common Mistakes\n- Using `v-model` on a prop directly (mutates parent state, breaks one-way flow)\n- Forgetting `.number` modifier when expecting numeric values (input value is always string)\n- Binding select `v-model` to a non-array when using `multiple` (causes Vue warning)\n- Using `v-model` on checkboxes without binding to boolean or array correctly\n\n## Best Practices\n- Always use `v-model` instead of manual `:value` + `@input` for form fields\n- Use `.trim` for text inputs to avoid accidental whitespace\n- Use `.number` for age, quantity, price inputs\n- Use `.lazy` for performance-heavy validation (validates on blur)\n- Group related checkboxes\u002Fradios using the same array\u002Fvariable\n\n## Performance Considerations\n- `v-model.lazy` reduces update frequency – good for expensive side effects (e.g., API search)\n- Thousands of form fields with `v-model` are still fine (Vue batches updates)\n\n## Production Recommendations\n- For complex forms, pair `v-model` with a validation library (VeeValidate, Zod)\n- Use `defineModel` for reusable form components\n- Combine `v-model` with `watch` to debounce expensive operations\n\n## Latest Vue Patterns\n- **Multiple `v-model` on components:** `\u003CChild v-model:firstName=\"first\" v-model:lastName=\"last\">`\n- **`defineModel` macro:** `const firstName = defineModel('firstName')` replaces prop + emit\n- **`v-model` modifiers on custom components** – `v-model.capitalize=\"myText\"`\n\n## Interview Tip\nWhen asked about `v-model` vs `v-bind`, explain that `v-bind` is one-way (parent→child), `v-model` is two-way but requires explicit event handling on components.\n\n## Common Follow-up\n*\"How does `v-model` work with checkboxes that have `true-value` and `false-value`?\"* – Vue allows custom true\u002Ffalse values: `\u003Cinput type=\"checkbox\" v-model=\"toggle\" true-value=\"yes\" false-value=\"no\">` – `toggle` becomes `\"yes\"` or `\"no\"` instead of boolean.\n\n## Real-world Example\nRegistration form:\n```vue\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"register\">\n    \u003Cinput v-model.trim=\"form.name\" placeholder=\"Name\" required>\n    \u003Cinput v-model.number=\"form.age\" type=\"number\" placeholder=\"Age\">\n    \n    \u003Cinput type=\"checkbox\" v-model=\"form.newsletter\"> Subscribe\n    \n    \u003Cselect v-model=\"form.country\">\n      \u003Coption value=\"us\">USA\u003C\u002Foption>\n      \u003Coption value=\"eu\">Europe\u003C\u002Foption>\n    \u003C\u002Fselect>\n    \n    \u003Ctextarea v-model.lazy=\"form.bio\" placeholder=\"Bio\">\u003C\u002Ftextarea>\n    \n    \u003Cbutton type=\"submit\">Register\u003C\u002Fbutton>\n  \u003C\u002Fform>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { reactive } from 'vue'\nconst form = reactive({\n  name: '',\n  age: null,\n  newsletter: false,\n  country: 'us',\n  bio: ''\n})\n\nfunction register() {\n  console.log(form)\n}\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\n`v-model` on text input uses `input` event (except `.lazy` uses `change`). On checkboxes\u002Fradios it uses `change` event for better accessibility. When using `.number` modifier, if `parseFloat()` returns `NaN`, the original value is kept.",[108,46,109,110],"forms","inputs","two-way-binding",{"id":112,"category":113,"question":114,"answer":115,"level":10,"tags":116},13,"Composition API","What is the Composition API and how does it differ from the Options API?","## Core Concept\nThe Composition API is a set of APIs (e.g., `ref`, `reactive`, `computed`, `watch`, lifecycle hooks) that allow you to write Vue components by importing functions instead of declaring options (`data`, `methods`, `computed`). It was introduced in Vue 3 to solve logic reuse and code organisation issues.\n\n**Key differences:**\n- **Options API:** Logic is grouped by option type (data, methods, computed). For a single feature, logic is scattered across several sections.\n- **Composition API:** Logic is grouped by feature – you can extract related code into composable functions.\n\n## Syntax\n```vue\n\u003C!-- Options API -->\n\u003Cscript>\nexport default {\n  data() {\n    return { count: 0 }\n  },\n  computed: {\n    double() { return this.count * 2 }\n  },\n  methods: {\n    increment() { this.count++ }\n  },\n  mounted() {\n    console.log('mounted')\n  }\n}\n\u003C\u002Fscript>\n\n\u003C!-- Composition API with \u003Cscript setup> (recommended) -->\n\u003Cscript setup>\nimport { ref, computed, onMounted } from 'vue'\nconst count = ref(0)\nconst double = computed(() => count.value * 2)\nfunction increment() { count.value++ }\nonMounted(() => console.log('mounted'))\n\u003C\u002Fscript>\n```\n\n## Execution Flow\n1. **Options API:** Vue creates a component instance, merges options, calls `data()` to create reactive state, binds methods and computed to `this`.\n2. **Composition API:** `setup()` (or `\u003Cscript setup>`) runs first, creating refs\u002Freactive objects. Vue then uses the returned values to render the template. Lifecycle hooks register callbacks that are executed at the right time.\n\n## Reactivity Explanation\nIn Options API, `data()` returns plain objects that Vue wraps with reactivity. In Composition API, you manually create reactive references using `ref` or `reactive`. Both use the same underlying Proxy system, but Composition API gives explicit control.\n\n## Practical Usage\n- **Options API:** Small to medium components, developers familiar with Vue 2.\n- **Composition API:** Large components, logic reuse across components, better TypeScript integration.\n\n## Interview Insight\nExplain that the Composition API does **not** replace the Options API – both coexist. Vue 3 supports both, and `\u003Cscript setup>` is now the recommended style for new projects.\n\n## Common Mistakes\n- Using Composition API but still writing huge monolithic `setup()` functions (defeats purpose)\n- Forgetting `.value` when using `ref` inside `setup()` but not in template\n- Mixing both APIs in the same component (possible but confusing)\n\n## Best Practices\n- Use `\u003Cscript setup>` for all new components\n- Extract reusable logic into composables (e.g., `useFetch`, `useMouse`)\n- Use `ref` for primitives and objects you will reassign; use `reactive` for objects with many properties you won't reassign\n\n## Performance Considerations\nComposition API has slightly lower overhead because it doesn't need to create wrapper objects for `data`, `methods`, etc. The difference is negligible for most apps.\n\n## Production Recommendations\n- Migrate legacy Options API components only when refactoring\n- Use ESLint plugin `vue\u002Fprefer-composition` to enforce Composition API style\n\n## Latest Vue Patterns\n- **`\u003Cscript setup>`** is now the default in Vite and Nuxt 3\n- **`defineProps`, `defineEmits`, `defineModel`** macros work only with `\u003Cscript setup>`\n- **`toValue`** utility for handling refs or plain values\n\n## Interview Tip\nEmphasise the **logic reuse advantage**: mixins (Options API) have naming conflicts and unclear data sources; composables (Composition API) are explicit, tree-shakable, and type-safe.\n\n## Common Follow-up\n*\"Can you use both Options and Composition APIs in the same component?\"* – Yes, but not recommended. You can have `\u003Cscript>` and `\u003Cscript setup>` together, but avoid mixing internal logic.\n\n## Real-world Example\nA component using a custom composable:\n```vue\n\u003C!-- useCounter.js -->\nexport function useCounter(initialValue = 0) {\n  const count = ref(initialValue)\n  const increment = () => count.value++\n  const decrement = () => count.value--\n  return { count, increment, decrement }\n}\n\n\u003C!-- MyComponent.vue -->\n\u003Cscript setup>\nimport { useCounter } from '.\u002FuseCounter'\nconst { count, increment, decrement } = useCounter(10)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cbutton @click=\"decrement\">-\u003C\u002Fbutton>\n  \u003Cspan>{{ count }}\u003C\u002Fspan>\n  \u003Cbutton @click=\"increment\">+\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nThe Composition API is also available as a plugin for Vue 2 (`@vue\u002Fcomposition-api`). The reactivity system (`@vue\u002Freactivity`) can be used standalone without Vue.",[117,118,119,14],"composition-api","options-api","script-setup",{"id":121,"category":122,"question":123,"answer":124,"level":10,"tags":125},14,"Reactivity","What is the difference between ref and reactive in Vue 3?","## Core Concept\n- **`ref`** wraps any value (primitive or object) into a reactive object with a `.value` property. It works for everything.\n- **`reactive`** makes an object itself reactive using a Proxy. It only works for object types (object, array, Map, Set).\n\n**Key insight:** `ref` is for values that you may reassign; `reactive` is for objects whose properties you mutate but never reassign the object itself.\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { ref, reactive } from 'vue'\n\n\u002F\u002F ref – works with any type\nconst count = ref(0)           \u002F\u002F { value: 0 }\nconst user = ref({ name: 'Alice' })  \u002F\u002F { value: { name: 'Alice' } }\n\n\u002F\u002F reactive – only objects\nconst state = reactive({\n  count: 0,\n  user: { name: 'Bob' }\n})\n\n\u002F\u002F Access in script\ncount.value++                   \u002F\u002F need .value\nstate.count++                   \u002F\u002F direct access\n\n\u002F\u002F Reassignment works with ref, not with reactive\nlet num = ref(10)\nnum = ref(20)                   \u002F\u002F works – new ref\n\nlet obj = reactive({ a: 1 })\nobj = reactive({ a: 2 })        \u002F\u002F breaks reactivity – lost original proxy\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003C!-- In template, ref automatically unwraps -->\n  \u003Cdiv>{{ count }}\u003C\u002Fdiv>        \u003C!-- no .value needed -->\n  \u003Cdiv>{{ state.count }}\u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. `ref(0)` creates a `RefImpl` instance with a getter\u002Fsetter that tracks the `effect` (e.g., component render).\n2. `reactive({})` creates a `Proxy` that traps property get\u002Fset and also tracks dependencies.\n3. When you mutate `ref.value`, the setter triggers effects. For `reactive`, property assignment triggers effects.\n\n## Reactivity Explanation\nBoth use Vue's Proxy-based reactivity. `ref` adds a `.value` wrapper to enable primitive reactivity (since Proxy can't wrap primitives). `reactive` works directly on objects but cannot be reassigned.\n\n## Practical Usage\n- **`ref`**: All primitives (string, number, boolean), arrays\u002Fobjects you will replace entirely, values from composables.\n- **`reactive`**: Component-level state objects that you mutate properties of, but never reassign the whole object.\n\n## Interview Insight\nExplain that `ref` is more versatile and the recommended default. `reactive` has limited use cases (form state objects, store state). Vue 3.4+ makes `ref` even better with `shallowRef` and custom `ref`.\n\n## Common Mistakes\n- Using `reactive` with primitive values (causes warning, does nothing)\n- Destructuring `reactive` object – loses reactivity (`const { count } = state`)\n- Forgetting `.value` when using `ref` in script (common source of bugs)\n- Reassigning `reactive` variable (breaks reactivity, use `Object.assign` instead)\n\n## Best Practices\n- Default to `ref` for everything\n- Use `reactive` only when you have a group of related properties and you won't reassign the container\n- Use `toRefs` to convert reactive object to refs for destructuring\n- Use `shallowRef` \u002F `shallowReactive` for large data that doesn't need deep reactivity\n\n## Performance Considerations\n- `reactive` is slightly faster for deep property access (no `.value` overhead)\n- `ref` creates an extra wrapper object (negligible overhead)\n- Deep reactivity on huge objects can be slow – use `shallowRef` + manual triggers\n\n## Production Recommendations\n- For component state, `ref` is safer and more predictable\n- For Pinia stores, use `ref` for simple values and `reactive` for complex state objects (or just `ref` everywhere)\n- Use `markRaw` to opt-out of deep reactivity for large read-only objects\n\n## Latest Vue Patterns\n- **`toValue`** utility (Vue 3.3+) unwraps refs, similar to `unref` but works with getters\n- **`defineModel`** returns a ref – consistent with `ref` usage\n- **`shallowRef`** for performance optimisation of large arrays\n\n## Interview Tip\nShow that `ref` can hold any type, while `reactive` cannot hold a primitive. Ask: *“How do you make a primitive reactive?”* – `ref`. Also mention that `ref` unwraps in templates and inside `reactive` (automatic).\n\n## Common Follow-up\n*\"Can you use `ref` and `reactive` together?\"* – Yes. Assigning a `ref` to a `reactive` property will automatically unwrap it. But it's clearer to stick to one.\n\n## Real-world Example\n```vue\n\u003Cscript setup>\nimport { ref, reactive, toRefs } from 'vue'\n\n\u002F\u002F ref for simple toggle and primitive\nconst isLoading = ref(false)\nconst pageTitle = ref('Dashboard')\n\n\u002F\u002F reactive for related form fields\nconst form = reactive({\n  email: '',\n  password: '',\n  rememberMe: false\n})\n\n\u002F\u002F If you need to destructure, convert to refs\nconst { email, password } = toRefs(form)\n\n\u002F\u002F Resetting form\nfunction resetForm() {\n  Object.assign(form, { email: '', password: '', rememberMe: false })\n}\n\n\u002F\u002F Replacing array (ref needed)\nconst items = ref([1, 2, 3])\nfunction replaceItems() {\n  items.value = [4, 5, 6]  \u002F\u002F works with ref, not with reactive\n}\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\n`ref` unwrapping in templates works only for top-level properties. For nested refs inside a reactive, you still need `.value`. Vue 3.4 improved debugging by adding `__v_skip` for custom refs.",[81,126,127,14],"ref","reactive",{"id":129,"category":7,"question":130,"answer":131,"level":10,"tags":132},15,"What is script setup and how does it simplify component authoring?","## Core Concept\n`\u003Cscript setup>` is a compile-time syntactic sugar for using the Composition API inside Single-File Components. It reduces boilerplate by allowing you to define props, emits, and reactive state without explicitly returning objects or using `setup()` function.\n\n**Key simplifications:**\n- No `export default` – code is directly executable\n- No `setup()` return – top-level bindings automatically exposed to template\n- Macros like `defineProps`, `defineEmits`, `defineModel` without importing\n- Better performance (less runtime overhead)\n\n## Syntax\n```vue\n\u003C!-- Without \u003Cscript setup> (regular Composition API) -->\n\u003Cscript>\nimport { ref, computed } from 'vue'\nexport default {\n  props: ['initialCount'],\n  emits: ['update'],\n  setup(props, { emit }) {\n    const count = ref(props.initialCount)\n    const double = computed(() => count.value * 2)\n    const increment = () => {\n      count.value++\n      emit('update', count.value)\n    }\n    return { count, double, increment }\n  }\n}\n\u003C\u002Fscript>\n\n\u003C!-- With \u003Cscript setup> -->\n\u003Cscript setup>\nimport { ref, computed } from 'vue'\nconst props = defineProps(['initialCount'])\nconst emit = defineEmits(['update'])\n\nconst count = ref(props.initialCount)\nconst double = computed(() => count.value * 2)\nconst increment = () => {\n  count.value++\n  emit('update', count.value)\n}\n\u002F\u002F Everything is auto-exposed to template\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv>{{ count }} x2 = {{ double }}\u003C\u002Fdiv>\n  \u003Cbutton @click=\"increment\">+1\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. At compile time, Vue transforms `\u003Cscript setup>` into a standard `setup()` function.\n2. All top-level variable declarations become return values.\n3. Macros like `defineProps` are replaced with actual runtime code.\n4. The component is processed as if written with explicit `setup()`.\n\n## Reactivity Explanation\nReactive refs created inside `\u003Cscript setup>` work exactly the same as in `setup()`. The difference is only syntactic.\n\n## Practical Usage\n- All new Vue 3 components\n- Component libraries, app views, composables\n- Quick prototyping\n\n## Interview Insight\nExplain that `\u003Cscript setup>` is **not a new API** but syntactic sugar. It compiles down to standard Composition API. It's the recommended way to write Vue components since 2022.\n\n## Common Mistakes\n- Using `defineProps` without importing (macro, fine) but trying to use it outside `\u003Cscript setup>` (won't work)\n- Destructuring `defineProps` loses reactivity (use `toRefs` if needed)\n- Assuming `this` exists inside `\u003Cscript setup>` (it doesn't)\n\n## Best Practices\n- Always use `\u003Cscript setup>` for new components\n- Use `defineProps` with TypeScript: `defineProps\u003C{ msg: string }>()`\n- Use `defineEmits` with validation: `defineEmits\u003C{ (e: 'submit', data: Form): void }>()`\n- Use `defineExpose` to expose methods to parent refs\n\n## Performance Considerations\n`\u003Cscript setup>` has slightly better runtime performance because it avoids creating intermediate option objects. The difference is minimal but measurable in large apps.\n\n## Production Recommendations\n- Enable `vite-plugin-vue` or `vue-loader` to handle `\u003Cscript setup>`\n- Use ESLint plugin `vue\u002Fscript-setup-uses-vars` to avoid unused variable warnings\n- Combine with `\u003Cstyle scoped>` for component-isolated CSS\n\n## Latest Vue Patterns\n- **`defineModel`** macro for two-way binding (Vue 3.4+)\n- **`defineOptions`** to set component name, inheritAttrs (Vue 3.3+)\n- **`defineSlots`** for type-safe slots\n- **Top-level await** inside `\u003Cscript setup>` (uses Suspense)\n\n## Interview Tip\nMention that `\u003Cscript setup>` enables **top-level await** – you can `await fetch()` directly without wrapping in an async function, but the parent component must use `\u003CSuspense>`.\n\n## Common Follow-up\n*\"Can you use `\u003Cscript setup>` alongside a regular `\u003Cscript>` tag?\"* – Yes. Use a normal `\u003Cscript>` for global options (e.g., `name`, `inheritAttrs`) and `\u003Cscript setup>` for logic. They are merged.\n\n## Real-world Example\n```vue\n\u003Cscript setup>\n\u002F\u002F Top-level await (needs Suspense wrapper)\nconst posts = await fetch('\u002Fapi\u002Fposts').then(r => r.json())\n\n\u002F\u002F Props with defaults\nconst props = defineProps\u003C{\n  title?: string\n  count?: number\n}>()\n\n\u002F\u002F Emits with validation\nconst emit = defineEmits\u003C{\n  (e: 'update', value: number): void\n  (e: 'delete', id: string): void\n}>()\n\n\u002F\u002F Expose method to parent\nconst reset = () => { \u002F* ... *\u002F }\ndefineExpose({ reset })\n\n\u002F\u002F Two-way binding macro\nconst modelValue = defineModel()  \u002F\u002F returns ref\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cinput v-model=\"modelValue\">\n  \u003Cbutton @click=\"emit('update', 42)\">Update\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\n`\u003Cscript setup>` uses **compiler macros** that are transformed at build time. They are not actual JavaScript functions. This allows Vue to optimise the generated code and provide better IDE support.",[119,117,133,134],"sfc","macros",{"id":136,"category":137,"question":138,"answer":139,"level":10,"tags":140},16,"Routing","How to set up basic routing in Vue.js with Vue Router 4?","## Core Concept\nVue Router is the official router for Vue.js. It integrates deeply with Vue's reactivity system to map URL paths to components, enabling Single-Page Application navigation without page reloads.\n\n**Key features:** Nested routes, dynamic route matching, navigation guards, lazy loading, and scroll control.\n\n## Syntax\n```js\n\u002F\u002F router\u002Findex.js\nimport { createRouter, createWebHistory } from 'vue-router'\nimport Home from '..\u002Fviews\u002FHome.vue'\n\nconst routes = [\n  {\n    path: '\u002F',\n    name: 'Home',\n    component: Home\n  },\n  {\n    path: '\u002Fabout',\n    name: 'About',\n    \u002F\u002F Lazy loading\n    component: () => import('..\u002Fviews\u002FAbout.vue')\n  },\n  {\n    path: '\u002Fuser\u002F:id',  \u002F\u002F dynamic segment\n    name: 'User',\n    component: () => import('..\u002Fviews\u002FUser.vue'),\n    props: true  \u002F\u002F pass route params as props\n  },\n  {\n    path: '\u002F:pathMatch(.*)*',  \u002F\u002F catch-all 404\n    name: 'NotFound',\n    component: () => import('..\u002Fviews\u002FNotFound.vue')\n  }\n]\n\nconst router = createRouter({\n  history: createWebHistory(),  \u002F\u002F HTML5 mode\n  routes\n})\n\nexport default router\n```\n\n```vue\n\u003C!-- App.vue -->\n\u003Ctemplate>\n  \u003Cnav>\n    \u003CRouterLink to=\"\u002F\">Home\u003C\u002FRouterLink>\n    \u003CRouterLink :to=\"{ name: 'About' }\">About\u003C\u002FRouterLink>\n    \u003CRouterLink :to=\"{ name: 'User', params: { id: 123 } }\">User 123\u003C\u002FRouterLink>\n  \u003C\u002Fnav>\n  \n  \u003C!-- Route view -->\n  \u003CRouterView \u002F>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { RouterLink, RouterView } from 'vue-router'\n\u003C\u002Fscript>\n```\n\n```vue\n\u003C!-- views\u002FUser.vue -->\n\u003Cscript setup>\nimport { useRoute, useRouter } from 'vue-router'\nconst route = useRoute()      \u002F\u002F access route info\nconst router = useRouter()    \u002F\u002F programmatic navigation\n\nconsole.log(route.params.id)  \u002F\u002F 123\n\nfunction goBack() {\n  router.back()\n}\n\nfunction goToHome() {\n  router.push('\u002F')\n  \u002F\u002F or router.push({ name: 'Home' })\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv>User ID: {{ $route.params.id }}\u003C\u002Fdiv>\n  \u003Cbutton @click=\"goBack\">Back\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. App initialises router with history mode.\n2. Router listens to URL changes (popstate events).\n3. When URL changes, router matches path to a route record.\n4. Router renders the corresponding component in `\u003CRouterView>`.\n5. Lazy-loaded components are fetched asynchronously.\n6. Navigation guards run before rendering.\n\n## Reactivity Explanation\n`$route` is a reactive object. When URL changes, `route.params`, `route.query` update, causing any component that uses them to re-render.\n\n## Practical Usage\n- Multi-page SPAs (dashboard, e-commerce, admin panels)\n- Nested layouts (e.g., \u002Fsettings\u002Fprofile, \u002Fsettings\u002Fsecurity)\n- Authentication-protected routes\n\n## Interview Insight\nExplain that Vue Router 4 is designed for Vue 3, with Composition API support. `useRoute()` and `useRouter()` replace `this.$route` and `this.$router`. Also mention `createWebHistory()` for clean URLs (requires server fallback).\n\n## Common Mistakes\n- Forgetting to provide the router to the app: `app.use(router)`\n- Using `\u003Ca href>` instead of `\u003CRouterLink>` (causes full page reload)\n- Not setting up server fallback for `createWebHistory` (404 on refresh)\n- Accessing `route.params` before the component is fully loaded (use `watch`)\n\n## Best Practices\n- Use named routes for better maintainability\n- Lazy-load all route components\n- Use `props: true` to decouple component from router\n- Implement navigation guards for auth: `router.beforeEach`\n\n## Performance Considerations\n- Lazy loading reduces initial bundle size\n- Use `router.push` over `router.replace` when you want history\n- Prefetch routes using webpack magic comments: `\u002F* webpackPrefetch: true *\u002F`\n\n## Production Recommendations\n- Use `createWebHistory()` for most SPAs (with nginx\u002FApache fallback)\n- Use `createWebHashHistory()` if server configuration not possible\n- Implement route-level code splitting\n- Add a loading indicator for lazy routes\n\n## Latest Vue Patterns\n- **Dynamic routing:** `router.addRoute()` for adding routes at runtime\n- **Route meta fields:** `meta: { requiresAuth: true }`\n- **Composition API guards:** `onBeforeRouteLeave`, `onBeforeRouteUpdate`\n\n## Interview Tip\nExplain the difference between `router.push` (adds to history) and `router.replace` (replaces current entry). Also mention `router.go(n)` for relative navigation.\n\n## Common Follow-up\n*\"How do you protect routes that require authentication?\"* – Use `router.beforeEach` guard to check auth state and redirect to login if needed.\n\n## Real-world Example\nAuth guard implementation:\n```js\n\u002F\u002F router\u002Findex.js\nrouter.beforeEach((to, from, next) => {\n  const isAuthenticated = localStorage.getItem('token')\n  \n  if (to.meta.requiresAuth && !isAuthenticated) {\n    next({ name: 'Login', query: { redirect: to.fullPath } })\n  } else if (to.name === 'Login' && isAuthenticated) {\n    next({ name: 'Dashboard' })\n  } else {\n    next()\n  }\n})\n```\n\n## Advanced Notes\nVue Router 4 supports **dynamic route matching with regex**: `path: '\u002Fuser\u002F:id(\\\\d+)'` restricts id to digits. Also supports **scroll behavior** customisation: `scrollBehavior(to, from, savedPosition)`. For **Server-Side Rendering**, use `createMemoryHistory()`.",[141,142,143,144],"routing","vue-router","spa","navigation",{"id":146,"category":7,"question":147,"answer":148,"level":10,"tags":149},17,"How to fetch data from an API in Vue? (fetch, async\u002Fawait, error handling)","## Core Concept\nData fetching in Vue is typically done inside lifecycle hooks (e.g., `onMounted`) using the browser's `fetch` API or libraries like `axios`. The fetched data is stored in reactive refs, and loading\u002Ferror states are managed manually.\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { ref, onMounted } from 'vue'\n\nconst data = ref(null)\nconst loading = ref(true)\nconst error = ref(null)\n\nasync function fetchData() {\n  loading.value = true\n  error.value = null\n  \n  try {\n    const response = await fetch('https:\u002F\u002Fapi.example.com\u002Fposts')\n    if (!response.ok) throw new Error(`HTTP ${response.status}`)\n    data.value = await response.json()\n  } catch (err) {\n    error.value = err.message\n  } finally {\n    loading.value = false\n  }\n}\n\nonMounted(() => {\n  fetchData()\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv v-if=\"loading\">Loading...\u003C\u002Fdiv>\n  \u003Cdiv v-else-if=\"error\">Error: {{ error }}\u003C\u002Fdiv>\n  \u003Cul v-else>\n    \u003Cli v-for=\"item in data\" :key=\"item.id\">{{ item.title }}\u003C\u002Fli>\n  \u003C\u002Ful>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. Component mounts → `onMounted` triggers `fetchData()`.\n2. `loading` becomes true, UI shows loading indicator.\n3. Fetch request is sent asynchronously.\n4. On response, data is parsed and stored in `data.value`.\n5. `loading` becomes false, UI renders the list.\n6. If error, `error` ref is set and error message displayed.\n\n## Reactivity Explanation\n`data`, `loading`, `error` are refs. When they are updated, Vue re-renders the component, showing appropriate UI based on their values.\n\n## Practical Usage\n- Loading user profiles, product lists, comments\n- Real-time dashboards (polling or WebSocket)\n- Form submissions (POST data to API)\n\n## Interview Insight\nExplain that `onMounted` is preferred over `setup()` for data fetching because `setup()` runs during server-side rendering (SSR) as well, potentially causing mismatches. For SSR, use `onServerPrefetch`.\n\n## Common Mistakes\n- Not handling loading\u002Ferror states (UI hangs or shows nothing)\n- Forgetting `await` before `response.json()`\n- Not checking `response.ok` (fetch only rejects on network errors, not HTTP errors)\n- Fetching data in `setup()` without considering SSR\n\n## Best Practices\n- Always include loading and error states\n- Use `try\u002Fcatch\u002Ffinally` for robust error handling\n- Cancel pending requests in `onBeforeUnmount` (using `AbortController`)\n- Extract fetch logic into composables (e.g., `useFetch`)\n- Use async\u002Fawait for readability\n\n## Performance Considerations\n- Avoid fetching the same data multiple times (cache or share refs)\n- Use `AbortController` to cancel stale requests when component unmounts or parameters change\n- Debounce search\u002Ffilter API calls\n- Consider using `keep-alive` to cache fetched data\n\n## Production Recommendations\n- Use `axios` for better error handling, interceptors, and timeout support\n- Add request\u002Fresponse interceptors for auth tokens\n- Implement retry logic for failed requests\n- Use `Promise.all` for parallel requests\n\n## Latest Vue Patterns\n- **`useFetch` from VueUse** – a ready-made composable that handles loading, error, and abort\n- **`\u003CSuspense>`** with async `setup()` (experimental but usable)\n- **`onServerPrefetch`** for SSR data fetching\n\n## Interview Tip\nExplain the **race condition** problem: if a component re-fetches quickly (e.g., search input), old request might resolve after new one and overwrite data. Solution: use `AbortController` or track request order.\n\n## Common Follow-up\n*\"How would you implement polling?\"* – Use `setInterval` inside `onMounted`, clear it in `onBeforeUnmount`, and update a ref that holds the data.\n\n## Real-world Example\n`useFetch` composable for reuse:\n```js\n\u002F\u002F composables\u002FuseFetch.js\nimport { ref } from 'vue'\n\nexport function useFetch(url) {\n  const data = ref(null)\n  const loading = ref(true)\n  const error = ref(null)\n\n  async function execute() {\n    loading.value = true\n    error.value = null\n    try {\n      const res = await fetch(url)\n      if (!res.ok) throw new Error(res.statusText)\n      data.value = await res.json()\n    } catch (e) {\n      error.value = e.message\n    } finally {\n      loading.value = false\n    }\n  }\n\n  execute()\n  return { data, loading, error, refetch: execute }\n}\n\n\u002F\u002F Usage in component\n\u003Cscript setup>\nimport { useFetch } from '.\u002Fcomposables\u002FuseFetch'\nconst { data, loading, error, refetch } = useFetch('\u002Fapi\u002Fposts')\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\nFor real-time updates, consider using WebSockets with `onMounted`\u002F`onBeforeUnmount`. For GraphQL, use `@vue\u002Fapollo-composable`. For caching and stale-while-revalidate patterns, look into `@tanstack\u002Fvue-query`.",[150,151,152,153,154],"fetching","api","async","error-handling","ajax",{"id":156,"category":157,"question":158,"answer":159,"level":10,"tags":160},18,"State Management","What is Pinia and how do you use it for basic state management?","## Core Concept\nPinia is the official state management library for Vue. It replaces Vuex and is designed with the Composition API, TypeScript, and modularity in mind. Each store is a separate module containing state, getters, and actions.\n\n**Key advantages over Vuex:** No mutations (only actions), better TypeScript inference, support for both Options and Composition API, and devtools integration.\n\n## Syntax\n```js\n\u002F\u002F stores\u002Fcounter.js\nimport { defineStore } from 'pinia'\n\nexport const useCounterStore = defineStore('counter', {\n  \u002F\u002F State (refs)\n  state: () => ({\n    count: 0,\n    name: 'Counter'\n  }),\n  \n  \u002F\u002F Getters (computed)\n  getters: {\n    doubleCount: (state) => state.count * 2,\n    displayText: (state) => `${state.name}: ${state.count}`\n  },\n  \n  \u002F\u002F Actions (methods)\n  actions: {\n    increment() {\n      this.count++\n    },\n    async fetchInitialCount() {\n      const res = await fetch('\u002Fapi\u002Fcount')\n      this.count = await res.json()\n    }\n  }\n})\n\n\u002F\u002F Or Composition API style (recommended)\nexport const useCounterStore = defineStore('counter', () => {\n  const count = ref(0)\n  const name = ref('Counter')\n  const doubleCount = computed(() => count.value * 2)\n  \n  function increment() {\n    count.value++\n  }\n  \n  async function fetchInitialCount() {\n    const res = await fetch('\u002Fapi\u002Fcount')\n    count.value = await res.json()\n  }\n  \n  return { count, name, doubleCount, increment, fetchInitialCount }\n})\n```\n\n```vue\n\u003C!-- Component using Pinia -->\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cp>{{ store.count }} x2 = {{ store.doubleCount }}\u003C\u002Fp>\n    \u003Cp>{{ store.displayText }}\u003C\u002Fp>\n    \u003Cbutton @click=\"store.increment\">+1\u003C\u002Fbutton>\n    \n    \u003C!-- Destructuring with storeToRefs to keep reactivity -->\n    \u003Cp>Destructured count: {{ count }}\u003C\u002Fp>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { useCounterStore } from '@\u002Fstores\u002Fcounter'\nimport { storeToRefs } from 'pinia'\n\nconst store = useCounterStore()\n\u002F\u002F Destructure state\u002Fgetters with storeToRefs\nconst { count, doubleCount, displayText } = storeToRefs(store)\n\u002F\u002F Actions can be destructured directly\nconst { increment } = store\n\u003C\u002Fscript>\n```\n\n## Execution Flow\n1. App initialises Pinia via `app.use(createPinia())`.\n2. First component calls `useCounterStore()` – creates store singleton.\n3. Store state is reactive; any mutation updates all components using that store.\n4. Actions can be async and commit no mutations – they directly modify state.\n\n## Reactivity Explanation\nPinia uses Vue's `ref` and `reactive` internally. Store state is deeply reactive. `storeToRefs` extracts refs so you can destructure without losing reactivity.\n\n## Practical Usage\n- Global user authentication state\n- Shopping cart across multiple components\n- Application settings\u002Ftheme\n- Shared data between unrelated components\n\n## Interview Insight\nExplain that Pinia is now the official recommendation (Vuex is in maintenance mode). Emphasise the **no mutations** simplification – actions directly modify state. Also mention **devtools** support out of the box.\n\n## Common Mistakes\n- Destructuring store without `storeToRefs` (breaks reactivity)\n- Using `defineStore` without unique ID (causes conflicts)\n- Calling actions inside getters (side effects in getters)\n- Not awaiting async actions when needed\n\n## Best Practices\n- Use Composition API style stores for better TypeScript and composable patterns\n- Keep actions async when needed; directly mutate state\n- Use `storeToRefs` when destructuring\n- Organise stores by domain (userStore, cartStore, productStore)\n\n## Performance Considerations\n- Pinia is very lightweight (≈1KB gzipped core)\n- Stores are lazy-initialised (created when first used)\n- Avoid putting non-reactive data in state (use `shallowRef` if needed)\n\n## Production Recommendations\n- Persist store state with `pinia-plugin-persistedstate` for localStorage\n- Use `store.$reset()` to reset to initial state\n- Combine with Vue Router for route-based store resetting\n\n## Latest Vue Patterns\n- **`defineStore` with setup store** – more flexible for advanced patterns\n- **`store.$patch`** for batch updates\n- **`store.$subscribe`** to react to state changes (watch alternative)\n\n## Interview Tip\nCompare Pinia and Vuex: Pinia has no mutations, better TS, module-based by default, and supports both Options and Composition API. Pinia actions can be async and call other stores.\n\n## Common Follow-up\n*\"Can you use Pinia with Vue 2?\"* – Yes, via `@pinia\u002Fnuxt` or `pinia` plugin for Vue 2.7+.\n\n## Real-world Example\nAuthentication store:\n```js\n\u002F\u002F stores\u002Fauth.js\nexport const useAuthStore = defineStore('auth', () => {\n  const user = ref(null)\n  const token = ref(localStorage.getItem('token'))\n  const isAuthenticated = computed(() => !!token.value)\n\n  async function login(email, password) {\n    const response = await fetch('\u002Fapi\u002Flogin', {\n      method: 'POST',\n      body: JSON.stringify({ email, password })\n    })\n    const data = await response.json()\n    token.value = data.token\n    user.value = data.user\n    localStorage.setItem('token', data.token)\n  }\n\n  function logout() {\n    token.value = null\n    user.value = null\n    localStorage.removeItem('token')\n  }\n\n  return { user, token, isAuthenticated, login, logout }\n})\n\n\u002F\u002F In component\nconst auth = useAuthStore()\nauth.login('user@example.com', 'pass')\n```\n\n## Advanced Notes\nPinia supports **cross-store composition**: you can call one store inside another store's action. Also supports **hot module replacement** during development. For large apps, consider splitting stores into multiple files and using `defineStore` with `id` unique across the app.",[161,162,163,164],"pinia","state-management","stores","vuex-alternative",{"id":166,"category":7,"question":167,"answer":168,"level":10,"tags":169},19,"What are ES modules and how are they used in Vue projects?","## Core Concept\nES Modules (ESM) is the standard JavaScript module system. It allows you to split code into separate files that can import and export functionality. Vue projects (using Vite or Vue CLI) natively support ES modules, enabling tree-shaking, better organisation, and asynchronous loading.\n\n**Key features:** `export` and `import` keywords, static analysis, and dynamic `import()` for code splitting.\n\n## Syntax\n```js\n\u002F\u002F utils\u002Fmath.js - named exports\nexport const add = (a, b) => a + b\nexport const multiply = (a, b) => a * b\nexport const PI = 3.14159\n\n\u002F\u002F Default export\nexport default function subtract(a, b) { return a - b }\n\n\u002F\u002F Component.vue - importing\n\u003Cscript setup>\n\u002F\u002F Named imports\nimport { add, multiply, PI } from '@\u002Futils\u002Fmath'\n\u002F\u002F Default import\nimport subtract from '@\u002Futils\u002Fmath'\n\u002F\u002F Alias\nimport * as math from '@\u002Futils\u002Fmath'\n\u002F\u002F Dynamic import (lazy)\nconst mathModule = await import('@\u002Futils\u002Fmath')\n\nconsole.log(add(2, 3))      \u002F\u002F 5\nconsole.log(subtract(5, 2)) \u002F\u002F 3\nconsole.log(PI)             \u002F\u002F 3.14159\n\u003C\u002Fscript>\n```\n\n## Execution Flow\n1. **Static imports** are resolved at compile time. Build tools analyse the dependency graph.\n2. **Dynamic imports** are resolved at runtime, returning a Promise.\n3. Browser loads modules in strict mode, deferring execution until all imports are ready.\n4. Vue components are compiled into JavaScript modules that export the component object.\n\n## Practical Usage\n- Organising utility functions, constants, composables, and stores\n- Lazy-loading routes (`() => import('.\u002Fviews\u002FAbout.vue')`)\n- Code-splitting for performance\n- Importing third-party libraries (most now support ESM)\n\n## Interview Insight\nExplain that modern Vue tooling (Vite) uses native ESM during development (no bundling), which enables fast HMR. Production builds still bundle for optimisation.\n\n## Common Mistakes\n- Using `require()` (CommonJS) in Vue SFCs – not fully supported in Vite\n- Forgetting `default` when importing a default export without braces\n- Mixing default and named exports incorrectly\n- Using `import` inside conditions (dynamic import required)\n\n## Best Practices\n- Prefer named exports over default exports for better tree-shaking\n- Use `@\u002F` alias for absolute imports (cleaner than relative paths)\n- Use dynamic imports for routes and heavy components\n- Keep imports organised (external libraries first, then internal)\n\n## Performance Considerations\n- Static imports are bundled, so no runtime cost\n- Dynamic imports reduce initial bundle size but add network latency\n- Tree-shaking removes unused named exports automatically\n\n## Production Recommendations\n- Configure `vite.config.js` to alias `@` to `src`\n- Use `import.meta.glob` in Vite for batch dynamic imports\n- Enable chunk splitting for dynamic imports\n\n## Latest Vue Patterns\n- **`import.meta.env`** for environment variables (Vite)\n- **`await import()`** top-level inside `\u003Cscript setup>` (needs `\u003CSuspense>`)\n- **Glob imports** for routing: `const modules = import.meta.glob('.\u002Fviews\u002F*.vue')`\n\n## Interview Tip\nExplain the difference between static and dynamic imports: static imports are hoisted and synchronously resolved; dynamic imports return a Promise and are useful for lazy loading.\n\n## Common Follow-up\n*\"How does tree-shaking work with ES modules?\"* – Build tools analyse static imports and remove code that is never imported. Named exports enable fine-grained tree-shaking; default exports may cause entire module to be kept.\n\n## Real-world Example\nLazy loading components in a Vue Router setup:\n```js\n\u002F\u002F router\u002Findex.js\nconst routes = [\n  {\n    path: '\u002Fdashboard',\n    component: () => import('@\u002Fviews\u002FDashboard.vue'),\n    \u002F\u002F Prefetch in production\n    component: () => import(\u002F* webpackPrefetch: true *\u002F '@\u002Fviews\u002FDashboard.vue')\n  }\n]\n\n\u002F\u002F Lazy load a heavy component in template\n\u003Ctemplate>\n  \u003CSuspense>\n    \u003Ctemplate #default>\n      \u003CLazyComponent \u002F>\n    \u003C\u002Ftemplate>\n    \u003Ctemplate #fallback>\n      Loading...\n    \u003C\u002Ftemplate>\n  \u003C\u002FSuspense>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { defineAsyncComponent } from 'vue'\nconst LazyComponent = defineAsyncComponent(() => import('.\u002FHeavyComponent.vue'))\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\nVite uses native ESM in development – each file is a module, enabling near-instant server start and HMR. In production, Vite bundles with Rollup, respecting ES modules' static structure for optimal tree-shaking.",[170,171,172,173,174],"es-modules","import","export","tree-shaking","lazy-loading",[176,184,191,197,205,214,220,228,237,243,247,252,259,265,271,280,286,294,303,310],{"id":6,"category":113,"question":177,"answer":178,"level":179,"tags":180},"Explain the deep differences between ref, reactive, shallowRef, and markRaw in Vue 3.","## Core Concept\n- **`ref`** wraps any value in a `RefImpl` object with deep reactivity. Changes to nested objects trigger updates.\n- **`reactive`** makes an object deeply reactive using Proxy, but cannot be reassigned.\n- **`shallowRef`** only tracks `.value` assignment, not nested mutations – good for large arrays.\n- **`markRaw`** marks an object so it will never be converted to reactive (opt-out of deep reactivity).\n\n## Syntax\n```ts\nimport { ref, reactive, shallowRef, markRaw, isReactive, isRef } from 'vue'\n\n\u002F\u002F ref – deep by default\nconst deep = ref({ user: { name: 'Alice' } })\ndeep.value.user.name = 'Bob'   \u002F\u002F triggers update\n\n\u002F\u002F shallowRef – only .value assignment triggers\ndeclare const shallow: ShallowRef\u003C{ user: { name: string } }>\nconst shallow = shallowRef({ user: { name: 'Alice' } })\nshallow.value.user.name = 'Bob' \u002F\u002F NO update\nshallow.value = { user: { name: 'Bob' } } \u002F\u002F triggers update\n\n\u002F\u002F reactive – deep, but object cannot be reassigned\nconst state = reactive({ count: 0 })\nstate.count = 1   \u002F\u002F works\n\u002F\u002F state = reactive({ count: 2 }) \u002F\u002F breaks reactivity\n\n\u002F\u002F markRaw – prevents reactivity\ndangerousExternalObject = markRaw({ sensitive: 'data' })\nconst wrapped = ref(dangerousExternalObject) \u002F\u002F not reactive\n```\n\n## Execution Flow\n1. `ref` creates a `RefImpl` that uses `toReactive()` internally for objects – calling `reactive()` on nested values.\n2. `shallowRef` creates a `RefImpl` with `_shallow = true` – it does not convert the value.\n3. `reactive` creates a Proxy that recursively converts all nested objects.\n4. `markRaw` sets `__v_skip = true` on the object – Proxy constructor skips it.\n\n## Reactivity Explanation\nDeep reactivity means Vue traverses the whole object graph and wraps every nested object. For very large objects (e.g., logs >10k entries), this can be slow. `shallowRef` leaves nested objects untouched, improving performance. `markRaw` is a compile-time hint to skip Proxification entirely.\n\n## Practical Usage\n- **`ref`**: Default choice, especially with primitives and small objects.\n- **`shallowRef`**: Large external data (e.g., database rows, logs), 3D model data, performance-critical lists.\n- **`reactive`**: Component-local state objects that won't be reassigned.\n- **`markRaw`**: Third-party libraries that expect plain objects, or huge read-only data (geojson, charts).\n\n## Interview Insight\nExplain that Vue's reactivity is opt-in and recursive by default. `shallowRef` is often overlooked – it's essential for performance when you control mutation logic manually (e.g., `triggerRef()` to force update).\n\n## Common Mistakes\n- Using `shallowRef` but expecting nested changes to trigger updates.\n- Using `reactive` for data that needs to be reassigned (use `ref` instead).\n- Forgetting that `shallowRef`'s `.value` is not reactive, but can hold a `reactive` object if needed.\n- Overusing `markRaw` and losing reactivity where needed.\n\n## Best Practices\n- Default to `ref` for all state.\n- Use `shallowRef` only when you measure a performance issue with deep reactivity.\n- Use `markRaw` for stable, large, external objects that never change.\n- Prefer `ref` over `reactive` in composables for flexibility.\n\n## Performance Considerations\n- `shallowRef` can drastically reduce initial render time for large arrays (e.g., 50k items).\n- `markRaw` prevents Proxy overhead and memory usage.\n- `triggerRef(shallowRef)` manually forces update after mutating nested data.\n\n## Production Recommendations\n- Profile reactive overhead with Vue Devtools before optimising.\n- For virtual scrolling, combine `shallowRef` with manual `triggerRef` after item updates.\n- Never `markRaw` data that will be mutated via reactive dependencies.\n\n## Latest Vue Patterns\n- **`shallowReactive`** – same as `shallowRef` but for object properties.\n- **`toRaw`** – retrieve the original raw object from a reactive proxy.\n- **`customRef`** – create your own ref with controlled track\u002Ftrigger.\n\n## Interview Tip\nAsk yourself: \"Do I need updates on deep property changes?\" If yes, use `ref`\u002F`reactive`. If you only need to replace the whole object, `shallowRef` is enough and faster.\n\n## Common Follow-up\n*\"Can you use `shallowRef` with `reactive` inside?\"* – Yes, but then the inner `reactive` object becomes deeply reactive while the outer wrapper remains shallow. Usually unnecessary.\n\n## Real-world Example\nLarge table with thousands of rows, only replacing entire dataset:\n```ts\nconst tableData = shallowRef\u003CRow[]>([])\n\nasync function fetchData() {\n  const rows = await api.get('\u002Fdata') \u002F\u002F huge array\n  tableData.value = rows \u002F\u002F triggers re-render once\n  \u002F\u002F No need to make each row reactive – huge performance gain\n}\n\n\u002F\u002F To update a single row manually:\nconst raw = tableData.value\nraw[index] = newRow\ntriggerRef(tableData) \u002F\u002F force update\n```\n\n## Advanced Notes\n`shallowRef`'s internal value is not made reactive, but you can still have reactive properties if you assign a `reactive` object. Use `triggerRef` after direct mutations. Vue 3.4+ improved `shallowRef` debugging in DevTools.","intermediate",[81,126,181,182,183],"shallowRef","markRaw","performance",{"id":17,"category":113,"question":185,"answer":186,"level":179,"tags":187},"How to use toRefs and toValue to preserve reactivity when destructuring or passing props?","## Core Concept\n- **`toRefs`** converts a reactive object into a plain object where each property is a ref pointing to the original object's property. This allows destructuring without losing reactivity.\n- **`toValue`** (Vue 3.3+) is a utility that normalises a `MaybeRefOrGetter\u003CT>` into a plain value. It unwraps refs and calls getters.\n\n## Syntax\n```ts\nimport { reactive, toRefs, toValue, ref, computed } from 'vue'\n\n\u002F\u002F toRefs example\nconst state = reactive({ count: 0, name: 'Vue' })\nconst { count, name } = toRefs(state)\n\u002F\u002F count is a ref, name is a ref\ncount.value++ \u002F\u002F updates state.count and triggers reactivity\n\n\u002F\u002F Without toRefs – breaks reactivity\nconst { count: brokenCount } = state \u002F\u002F plain number, not reactive\n\n\u002F\u002F toValue example (Vue 3.3+)\nfunction useDouble(value: MaybeRefOrGetter\u003Cnumber>) {\n  return computed(() => toValue(value) * 2)\n}\n\nconst rawNumber = 5\nconst reactiveNumber = ref(10)\nconst getterNumber = () => 15\n\nuseDouble(rawNumber)       \u002F\u002F computed => 10\nuseDouble(reactiveNumber)  \u002F\u002F computed => 20, updates when reactiveNumber changes\nuseDouble(getterNumber)    \u002F\u002F computed => 30\n```\n\n## Execution Flow\n1. `toRefs` creates a `ref` for each property by calling `toRef(state, key)`.\n2. Each `toRef` creates a ref that proxies get\u002Fset to the original reactive object.\n3. `toValue` checks the input: if it's a ref, returns `.value`; if it's a function, calls it; otherwise returns the input.\n\n## Reactivity Explanation\n`toRefs` preserves the reactive connection: the created refs share the same source as the original reactive object. `toValue` is a one-time read (like `unref` but also handles getters) – it does not create a reactive dependency automatically unless used inside a reactive scope (computed\u002Fwatch).\n\n## Practical Usage\n- **`toRefs`**: Destructuring `reactive` objects in composable return values, converting `reactive` to refs for prop passing.\n- **`toValue`**: Writing flexible composables that accept plain values, refs, or getters; simplifying logic in `watch` and `computed`.\n\n## Interview Insight\nExplain that `toRefs` solves the destructuring problem of `reactive` – a common interview trap. `toValue` is newer and often compared to `unref`, but it also handles functions, making it ideal for composables that accept lazy values.\n\n## Common Mistakes\n- Using `toRefs` on a `ref` (works but unnecessary – ref is already a single ref).\n- Destructuring `reactive` without `toRefs` and then wondering why reactivity is lost.\n- Using `toValue` inside `computed` without realising that the computed will not re-run if a getter's dependencies change (getters are not tracked).\n\n## Best Practices\n- Always use `toRefs` when returning a reactive object from a composable to allow destructuring.\n- Use `toValue` for function arguments that can be ref or plain value, especially in composables.\n- Prefer `toRefs` over manually creating `ref` for each property.\n\n## Performance Considerations\n`toRefs` is cheap – it creates lightweight proxy refs. `toValue` is also cheap (just property access). Neither causes deep cloning.\n\n## Production Recommendations\n- In TypeScript, use `MaybeRefOrGetter\u003CT>` type for arguments that accept ref\u002Fvalue\u002Fgetter.\n- Combine `toValue` with `watch` to react to changes when needed.\n\n## Latest Vue Patterns\n- **`toRef`** – create a single ref from a reactive object property.\n- **`toValue`** is part of Vue 3.3+; for older versions use `unref` plus manual getter check.\n- `toValue` is used inside `watch` and `watchEffect` automatically for getters.\n\n## Interview Tip\nShow that `toRefs` is different from `toRef`: `toRefs` does all properties at once. Mention that you can also use `toRefs` on a `reactive` object from Pinia stores to destructure safely.\n\n## Common Follow-up\n*\"What happens if you call `toRefs` on a ref?\"* – You get an object with a `value` property that is a ref, effectively `{ value: originalRef }`. Not useful, but not broken.\n\n## Real-world Example\nComposable that accepts flexible input and preserves reactivity:\n```ts\nimport { toValue, computed, ref, type MaybeRefOrGetter } from 'vue'\n\nfunction useFilteredList(\n  source: MaybeRefOrGetter\u003Cany[]>,\n  filterText: MaybeRefOrGetter\u003Cstring>\n) {\n  const filtered = computed(() => {\n    const list = toValue(source)\n    const search = toValue(filterText).toLowerCase()\n    return list.filter(item => item.name.toLowerCase().includes(search))\n  })\n  return { filtered }\n}\n\n\u002F\u002F Usage\nconst allItems = ref([{ name: 'Apple' }, { name: 'Banana' }])\nconst search = ref('ap')\nconst { filtered } = useFilteredList(allItems, search)\n\u002F\u002F filtered updates reactively when allItems or search changes\n\n\u002F\u002F Also works with plain values or getters\nconst { filtered: staticFilter } = useFilteredList(\n  [{ name: 'Apple' }], \n  () => 'app'\n)\n```\n\n## Advanced Notes\n`toValue` is essentially `unref` + support for getters. It does **not** track getter dependencies; use `computed` if you need reactivity. Inside `watch` and `watchEffect`, passing a getter already works because they handle it specially.",[81,188,189,190],"toRefs","toValue","destructuring",{"id":24,"category":122,"question":192,"answer":193,"level":179,"tags":194},"What is the difference between watch, watchEffect, watchPostEffect, and watchSyncEffect?","## Core Concept\n- **`watch`** – lazy, explicit source tracking, access to old\u002Fnew values, runs after DOM updates by default.\n- **`watchEffect`** – immediate, automatic dependency tracking, runs reactively, cannot access old values.\n- **`watchPostEffect`** – alias for `watchEffect` with `flush: 'post'` (after DOM updates).\n- **`watchSyncEffect`** – alias for `watchEffect` with `flush: 'sync'` (synchronous, before DOM updates).\n\n## Syntax\n```ts\nimport { ref, watch, watchEffect, watchPostEffect, watchSyncEffect } from 'vue'\n\nconst count = ref(0)\nconst name = ref('Alice')\n\n\u002F\u002F watch – explicit sources\nwatch(count, (newVal, oldVal) => {\n  console.log(`count changed from ${oldVal} to ${newVal}`)\n})\n\n\u002F\u002F watch multiple sources\nwatch([count, name], ([newCount, newName], [oldCount, oldName]) => {\n  console.log('Either changed')\n})\n\n\u002F\u002F watchEffect – auto dependencies\nwatchEffect(() => {\n  console.log(`Count is ${count.value}, name is ${name.value}`)\n  \u002F\u002F runs immediately, then whenever count or name changes\n})\n\n\u002F\u002F flush options\nwatchEffect(() => {}, { flush: 'pre' })  \u002F\u002F default, before DOM\nwatchPostEffect(() => {})                \u002F\u002F after DOM\nwatchSyncEffect(() => {})                \u002F\u002F sync, before Vue's scheduler\n```\n\n## Execution Flow\n1. **`watch`**: On creation, it does not run. When one of the tracked sources changes, it schedules a job. After the component updates (or immediately with `immediate: true`), it runs the callback.\n2. **`watchEffect`**: Runs immediately, tracks any reactive property accessed inside. When any dependency changes, it re-runs.\n3. **`watchPostEffect`**: Same as `watchEffect` but the effect is queued after DOM updates – useful for accessing updated DOM.\n4. **`watchSyncEffect`**: Forces synchronous execution – no batching; runs before Vue's nextTick. Use sparingly.\n\n## Reactivity Explanation\n`watch` creates a dependency on explicitly defined sources. `watchEffect` creates a reactive effect that auto-collects dependencies during its execution – similar to `computed` but for side effects.\n\n## Practical Usage\n- **`watch`**: Need old value, lazy initial run, watching specific props, debouncing.\n- **`watchEffect`**: Side effects that depend on multiple reactive sources, auto-tracked.\n- **`watchPostEffect`**: Accessing DOM after state change (e.g., focus management, scroll).\n- **`watchSyncEffect`**: Immediate synchronous side effects (rare; may cause performance issues).\n\n## Interview Insight\nExplain that `watchEffect` is declarative and eliminates boilerplate, but cannot access the previous value. `watch` is more imperative and explicit. Also mention that `watchPostEffect` is the go-to for DOM manipulation because it runs after Vue patches the DOM.\n\n## Common Mistakes\n- Mutating watched state inside `watch` without `flush: 'post'` causing infinite loops.\n- Using `watchEffect` when you need old value – impossible, use `watch`.\n- Forgetting that `watchEffect` runs immediately – may cause unintended side effects on mount.\n- Overusing `watchSyncEffect` – it breaks Vue's batching and can degrade performance.\n\n## Best Practices\n- Prefer `watch` when you need to compare previous\u002Fcurrent values.\n- Prefer `watchEffect` for independent side effects like logging, API calls that don't need old data.\n- Use `watchPostEffect` for DOM-related effects (e.g., `element.focus()`).\n- Avoid `watchSyncEffect` unless you fully understand scheduler implications.\n\n## Performance Considerations\n- `watchEffect` may re-run more often than necessary if you access many reactive objects.\n- Sync watchers (`flush: 'sync'`) run synchronously, potentially causing multiple re-renders in one tick.\n- Post watchers (`post`) are efficient because they run after batching.\n\n## Production Recommendations\n- For production forms, use `watch` with debounce to avoid excessive validation on every keystroke.\n- Use `watchEffect` with `onCleanup` to cancel pending async requests.\n- In SSR, avoid `watchPostEffect` because there is no DOM on server – wrap in client-only check.\n\n## Latest Vue Patterns\n- **`onWatcherCleanup`** (Vue 3.5+) – register cleanup for async watchers.\n- **`watch` with `once: true`** (Vue 3.4+) – run callback only once.\n- **`watchEffect` with `onCleanup`** – cancel previous async operations.\n\n## Interview Tip\nCompare `watch` vs `watchEffect` with an example: fetching data when an ID changes. `watch` needs `immediate: true`, `watchEffect` handles it automatically but cannot access previous ID for loading state.\n\n## Common Follow-up\n*\"How do you cancel an async request in watchEffect?\"* – Use the `onCleanup` function passed to the effect callback.\n\n## Real-world Example\nSearch component with debounced API call:\n```ts\nimport { ref, watch, watchPostEffect } from 'vue'\n\nconst searchTerm = ref('')\nconst results = ref([])\nconst loading = ref(false)\n\n\u002F\u002F Debounced API call using watch\nlet timeoutId: NodeJS.Timeout\nwatch(searchTerm, (newVal) => {\n  clearTimeout(timeoutId)\n  loading.value = true\n  timeoutId = setTimeout(async () => {\n    results.value = await fetchSearch(newVal)\n    loading.value = false\n  }, 300)\n})\n\n\u002F\u002F Focus input after component updates (post-effect)\nconst inputRef = ref\u003CHTMLInputElement>()\nwatchPostEffect(() => {\n  inputRef.value?.focus() \u002F\u002F runs after DOM update\n})\n\n\u002F\u002F Auto-track effect for logging\nwatchEffect(() => {\n  console.log(`Search term: ${searchTerm.value}, results count: ${results.value.length}`)\n})\n```\n\n## Advanced Notes\n`watchEffect` flushes `'pre'` by default, meaning it runs before component updates. This may cause stale DOM reads. Use `watchPostEffect` for DOM reads. The scheduler batches effects; `sync` bypasses batching. Vue 3.5 improved `watch` with better TypeScript inference for multiple sources.",[195,80,196,81],"watchers","watchEffect",{"id":32,"category":113,"question":198,"answer":199,"level":179,"tags":200},"How to build advanced composables with lifecycle integration, cleanup, and TypeScript?","## Core Concept\nComposables are reusable stateful functions that leverage the Composition API. Advanced composables manage their own lifecycle (onMounted, onUnmounted), handle cleanup, accept reactive parameters, return reactive state, and are fully typed.\n\n**Key patterns:** reactive parameters via `MaybeRefOrGetter`, return type inference, automatic cleanup on unmount, and integration with Vue's reactivity system.\n\n## Syntax\n```ts\n\u002F\u002F composables\u002FuseMouse.ts\nimport { ref, onMounted, onUnmounted, type Ref, watchEffect } from 'vue'\n\nexport function useMouse(target?: Ref\u003CHTMLElement | null>) {\n  const x = ref(0)\n  const y = ref(0)\n  let cleanup: (() => void) | undefined\n\n  function update(event: MouseEvent) {\n    x.value = event.clientX\n    y.value = event.clientY\n  }\n\n  function startListening() {\n    const element = target?.value || window\n    element.addEventListener('mousemove', update)\n    cleanup = () => element.removeEventListener('mousemove', update)\n  }\n\n  onMounted(() => startListening())\n  onUnmounted(() => cleanup?.())\n\n  \u002F\u002F Re-run if target changes\n  if (target) {\n    watchEffect((onCleanup) => {\n      startListening()\n      onCleanup(() => cleanup?.())\n    })\n  }\n\n  return { x, y }\n}\n```\n\n## Execution Flow\n1. Composables are called inside `setup()` or `\u003Cscript setup>`.\n2. They create reactive state (refs, reactive).\n3. Lifecycle hooks (`onMounted`, etc.) are registered on the calling component instance.\n4. When component unmounts, all registered cleanup functions run.\n5. Composables can accept reactive parameters; using `watchEffect` or `toValue` to react to changes.\n\n## Reactivity Explanation\nComposables run in the context of the component's reactive scope. `watch`, `watchEffect`, and `computed` created inside a composable are automatically cleaned up when the component unmounts. Returned refs are reactive and cause the component to re-render.\n\n## Practical Usage\n- Abstracting mouse\u002Ftrackpad events, window resize, local storage sync\n- Complex form logic with validation\n- WebSocket connections with auto-reconnect\n- Infinite scrolling, intersection observers\n\n## Interview Insight\nExplain that composables are not just functions – they leverage Vue's reactivity and lifecycle. A composable that doesn't use reactive state or hooks could be a plain utility. Advanced composables handle cleanup to prevent memory leaks.\n\n## Common Mistakes\n- Forgetting to clean up event listeners \u002F intervals \u002F observers in `onUnmounted`.\n- Calling composables outside of `setup()` (e.g., in plain event handlers) – lifecycle hooks will not work.\n- Overusing `reactive` inside composables that return objects – prefer `ref` for flexibility.\n- Not using `toValue` for flexible parameters, causing the composable to not react to ref changes.\n\n## Best Practices\n- Return a plain object with refs, not reactive (allows destructuring with `toRefs`).\n- Accept parameters as `MaybeRefOrGetter\u003CT>` for flexibility.\n- Use `onCleanup` inside `watchEffect` for cancelling async requests.\n- Provide TypeScript overloads or generic parameters for complex types.\n- Name composables starting with `use` (convention).\n\n## Performance Considerations\n- Composables are cheap; each component call creates new refs\u002Fhooks.\n- Avoid creating heavy internal watchers unless needed; prefer manual event listeners.\n- Use `shallowRef` for large data inside composables that doesn't need deep reactivity.\n\n## Production Recommendations\n- Test composables independently using `@vue\u002Ftest-utils` or `@vue\u002Fcomposition-api` standalone.\n- Document composable parameters and return types for team reuse.\n- Use `vueuse` library as reference; many patterns already exist.\n\n## Latest Vue Patterns\n- **`toValue`** for handling `MaybeRefOrGetter` in parameters.\n- **`watchEffect` with `onCleanup`** for async request management.\n- **`inject` \u002F `provide` inside composables** for global configuration.\n- **`effectScope`** for advanced composables that need manual grouping of effects.\n\n## Interview Tip\nShow a composable that cleans up: `useEventListener`, `useInterval`, `useWebSocket`. Mention the `onCleanup` pattern in `watchEffect` for cancelling async requests.\n\n## Common Follow-up\n*\"How do you share state between multiple components using a composable?\"* – Store state outside the composable function (module-level ref) to make it a singleton.\n\n## Real-world Example\n`useWebSocket` composable:\n```ts\nimport { ref, onUnmounted, watchEffect, type MaybeRefOrGetter, toValue } from 'vue'\n\nexport function useWebSocket(url: MaybeRefOrGetter\u003Cstring>) {\n  const data = ref\u003Cany>(null)\n  const status = ref\u003C'connecting' | 'open' | 'closing' | 'closed'>('connecting')\n  let ws: WebSocket | null = null\n\n  function connect() {\n    const resolvedUrl = toValue(url)\n    ws = new WebSocket(resolvedUrl)\n    ws.onopen = () => { status.value = 'open' }\n    ws.onmessage = (e) => { data.value = JSON.parse(e.data) }\n    ws.onclose = () => { status.value = 'closed' }\n    ws.onerror = () => { status.value = 'closed' }\n  }\n\n  function disconnect() {\n    ws?.close()\n    ws = null\n  }\n\n  watchEffect((onCleanup) => {\n    connect()\n    onCleanup(() => disconnect())\n  })\n\n  onUnmounted(() => disconnect())\n\n  return { data, status, disconnect, reconnect: connect }\n}\n```\n\n## Advanced Notes\nComposables can be nested – a composable can call another composable. Vue 3.2+ introduced `effectScope` to group effects and manually stop them, which is useful for advanced patterns like cancellable composables. Also, composables can accept `Ref` parameters and return `Ref`; TypeScript inference works best with generic constraints.",[201,202,98,203,204],"composables","reusability","typescript","cleanup",{"id":41,"category":206,"question":207,"answer":208,"level":179,"tags":209},"Components","How to use dynamic components, KeepAlive, and Teleport in Vue 3?","## Core Concept\n- **Dynamic components** (`\u003Ccomponent :is=\"...\">`) switch between components at runtime.\n- **KeepAlive** caches inactive component instances, preserving state and avoiding re-renders.\n- **Teleport** renders a component's template content at a different DOM location (e.g., modals, toasts).\n\n## Syntax\n```vue\n\u003Ctemplate>\n  \u003C!-- Dynamic component -->\n  \u003Ccomponent :is=\"currentTab\" :key=\"currentTab\" \u002F>\n  \n  \u003C!-- With KeepAlive (caches tabs) -->\n  \u003CKeepAlive :include=\"['TabA', 'TabB']\" :max=\"10\">\n    \u003Ccomponent :is=\"currentTab\" \u002F>\n  \u003C\u002FKeepAlive>\n  \n  \u003C!-- Teleport to body (modal) -->\n  \u003CTeleport to=\"body\">\n    \u003Cdiv v-if=\"showModal\" class=\"modal\">\n      \u003Cp>Modal content\u003C\u002Fp>\n    \u003C\u002Fdiv>\n  \u003C\u002FTeleport>\n  \n  \u003C!-- Teleport with multiple targets using selector -->\n  \u003CTeleport to=\"#portal-target\">\n    \u003CToast \u002F>\n  \u003C\u002FTeleport>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { ref, shallowRef } from 'vue'\nimport TabA from '.\u002FTabA.vue'\nimport TabB from '.\u002FTabB.vue'\n\nconst currentTab = shallowRef(TabA)  \u002F\u002F shallowRef for component\nconst showModal = ref(false)\n\u003C\u002Fscript>\n```\n\n## Execution Flow\n1. **Dynamic component**: Vue checks `:is` value – if it's a component definition, it renders that component; if a string, resolves from global\u002Flocal registration.\n2. **KeepAlive**: When switching away, the component instance is cached (not unmounted). `onDeactivated` hook runs; when switched back, cached instance is reused, `onActivated` runs.\n3. **Teleport**: In the template, Teleport is a placeholder. Vue renders its children but moves the DOM nodes to the specified target element after mount.\n\n## Reactivity Explanation\n`KeepAlive` preserves reactive state because the component instance is not destroyed. `Teleport` does not affect reactivity; reactive updates still work normally, but the DOM is elsewhere.\n\n## Practical Usage\n- **Dynamic components**: Tab interfaces, wizard steps, conditional layout injection.\n- **KeepAlive**: Multi-step forms (preserve input data), dashboards with route caching, expensive charts.\n- **Teleport**: Modals, dropdowns, tooltips, notification toasts, full-screen overlays.\n\n## Interview Insight\nExplain that `KeepAlive` is different from `v-show` – it actually caches the component instance and state, while `v-show` only toggles CSS. Teleport solves stacking context and overflow issues for modals.\n\n## Common Mistakes\n- Forgetting `:key` when switching dynamic components of the same type (Vue reuses component, may cause issues).\n- Using `KeepAlive` without `include`\u002F`exclude` – caches all, may cause memory issues.\n- Teleport target not existing in DOM when component mounts – use `disabled` prop or mount later.\n- Nesting Teleport inside conditional – ensure target is available.\n\n## Best Practices\n- Use `shallowRef` for component references to avoid deep reactivity.\n- Set `max` on `KeepAlive` to limit cache size.\n- Use `onActivated`\u002F`onDeactivated` for refresh logic in cached components.\n- For Teleport, always ensure target exists (e.g., `document.body` is safe, custom divs may not be ready).\n\n## Performance Considerations\n- `KeepAlive` increases memory usage (keeps component instances). Set `max` to limit.\n- Teleport has negligible performance cost.\n- Dynamic component switches trigger full component lifecycle (unless cached).\n\n## Production Recommendations\n- Cache route views with `KeepAlive` in Vue Router: `\u003CRouterView v-slot=\"{ Component }\">\u003CKeepAlive>\u003Ccomponent :is=\"Component\" \u002F>\u003C\u002FKeepAlive>\u003C\u002FRouterView>`.\n- Use Teleport for modals to avoid z-index issues, but manage focus for accessibility.\n- For portals that need SSR, use `ClientOnly` wrapper or disable Teleport on server.\n\n## Latest Vue Patterns\n- **`\u003CSuspense>`** can be combined with `\u003CKeepAlive>` for async components.\n- **Multiple teleport targets** using same selector – they will append in order.\n- **Teleport with `disabled`** – conditionally render in-place or teleport.\n\n## Interview Tip\nShow how `KeepAlive` includes\u002Fexcludes can be dynamic: `:include=\"cachedComponents\"` where `cachedComponents` is a ref array of component names.\n\n## Common Follow-up\n*\"How does KeepAlive work with dynamic components when the component names change?\"* – It caches by component type. If you switch between two different components, each gets its own cache entry.\n\n## Real-world Example\nTab interface with cached form data and teleported modal:\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cbutton v-for=\"tab in tabs\" @click=\"currentTab = tab.component\">\n      {{ tab.name }}\n    \u003C\u002Fbutton>\n\n    \u003CKeepAlive :include=\"['ProfileForm', 'SettingsForm']\" :max=\"2\">\n      \u003Ccomponent :is=\"currentTab\" :key=\"currentTab.__name\" \u002F>\n    \u003C\u002FKeepAlive>\n\n    \u003CTeleport to=\"body\">\n      \u003Cdiv v-if=\"showModal\" class=\"modal-overlay\" @click.self=\"showModal = false\">\n        \u003Cdiv class=\"modal\">\n          \u003Ch3>Unsaved changes\u003C\u002Fh3>\n          \u003Cbutton @click=\"saveAndClose\">Save\u003C\u002Fbutton>\n          \u003Cbutton @click=\"discardAndClose\">Discard\u003C\u002Fbutton>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002FTeleport>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\n`KeepAlive` uses a `Map` with component `type` as key. If you have multiple instances of the same component, they share the same cache entry unless you provide a unique `key`. Teleport uses `appendChild` to move nodes; after moving, event listeners and reactivity remain intact. For SSR, Teleport content will not be teleported on server – you must ensure client-only rendering.",[210,211,212,213],"dynamic-components","keepalive","teleport","caching",{"id":50,"category":206,"question":215,"answer":216,"level":179,"tags":217},"What is provide\u002Finject and how to use it for dependency injection in deep component trees?","## Core Concept\n`provide` and `inject` allow ancestor components to provide dependencies (data or methods) to all descendant components, regardless of depth, without passing props through every level (prop drilling).\n\n**Key features:** reactive injection (via refs), optional default values, symbols for uniqueness, and type safety with TypeScript.\n\n## Syntax\n```vue\n\u003C!-- Ancestor.vue -->\n\u003Cscript setup>\nimport { provide, ref, readonly } from 'vue'\nimport { injectionKey } from '.\u002Fkeys'\n\nconst theme = ref('dark')\nconst user = ref({ name: 'Alice' })\n\nfunction updateTheme(newTheme: string) {\n  theme.value = newTheme\n}\n\n\u002F\u002F Provide reactive values\nprovide('theme', theme)                     \u002F\u002F string key\nprovide('user', readonly(user))             \u002F\u002F readonly to prevent mutations\nprovide('updateTheme', updateTheme)          \u002F\u002F function\nprovide(injectionKey, 'value')              \u002F\u002F symbol key for TypeScript\n\u003C\u002Fscript>\n\n\u003C!-- Descendant.vue -->\n\u003Cscript setup>\nimport { inject } from 'vue'\nimport { injectionKey } from '.\u002Fkeys'\n\n\u002F\u002F Inject with default value\nconst theme = inject('theme', 'light')\nconst updateTheme = inject('updateTheme')\nconst user = inject('user', { name: 'Guest' }, true) \u002F\u002F true = treat as default\n\n\u002F\u002F Type-safe injection with symbol key\nconst typedValue = inject(injectionKey) \u002F\u002F TypeScript infers type\n\n\u002F\u002F Optional injection (may be undefined)\nconst optional = inject('optional', null)\n\u003C\u002Fscript>\n```\n\n## Execution Flow\n1. In ancestor, `provide` stores a value in a component-scoped map.\n2. Descendant calls `inject` which traverses the parent chain looking for the key.\n3. If found, returns the provided value; if not, returns default or throws (in dev).\n4. If value is a ref, the descendant establishes a reactive connection – changes in ancestor cause descendant re-renders.\n\n## Reactivity Explanation\nWhen you provide a `ref`, the descendant's `inject` returns the same ref object. Mutating the ref in ancestor triggers reactivity in descendant. For plain objects\u002Fvalues, no automatic reactivity; provide a `ref` or `computed` for reactivity.\n\n## Practical Usage\n- Theming (dark\u002Flight mode)\n- User authentication state\n- Global configuration (API base URL, feature flags)\n- Locale \u002F i18n\n- Cross-cutting concerns (analytics, logging)\n\n## Interview Insight\nExplain that `provide\u002Finject` is not a full state management solution (like Pinia) because it doesn't have a central store, devtools, or persistence. It's best for shared dependencies that are scoped to a component subtree.\n\n## Common Mistakes\n- Providing a plain value but expecting it to be reactive (provide a ref instead).\n- Mutating provided objects in descendant (breaks unidirectional flow – use `readonly`).\n- Using string keys that may collide (use `Symbol()` or injection keys).\n- Overusing provide\u002Finject for shallow hierarchies (props are clearer).\n\n## Best Practices\n- Use `Symbol()` or `InjectionKey\u003CT>` for type-safe keys.\n- Provide `readonly(ref)` to prevent descendants from mutating state.\n- Provide functions for state updates (like `updateTheme`) to maintain unidirectional flow.\n- Provide default values to avoid `undefined` checks.\n- Document provided keys in a shared `keys.ts` file.\n\n## Performance Considerations\n`provide\u002Finject` is efficient – it's just property lookups up the parent chain. No performance penalty for deep trees.\n\n## Production Recommendations\n- Combine with `readonly` to enforce immutability.\n- For large apps, still prefer Pinia for global state; provide\u002Finject for subtree-scoped dependencies.\n- In SSR, provide is per-request; no special handling needed.\n\n## Latest Vue Patterns\n- **`InjectionKey\u003CT>`** utility for TypeScript: `export const MyKey: InjectionKey\u003CMyType> = Symbol()`.\n- **Provide\u002FInject with composables** – encapsulate injection logic in a composable (e.g., `useTheme`).\n- **`provide` with `ref` and `computed`** for reactive derived state.\n\n## Interview Tip\nContrast with props: props are explicit, type-safe, and trigger updates, but cause prop drilling. Provide\u002Finject is implicit, great for deep trees but harder to trace. Use both appropriately.\n\n## Common Follow-up\n*\"How do you test components that use provide\u002Finject?\"* – Use `@vue\u002Ftest-utils` `global.provide` to mock provided values.\n\n## Real-world Example\nTheme composable that encapsulates provide\u002Finject:\n```ts\n\u002F\u002F composables\u002Ftheme.ts\nimport { provide, inject, ref, readonly, type InjectionKey, type Ref } from 'vue'\n\nexport type Theme = 'light' | 'dark'\nexport const ThemeKey: InjectionKey\u003C{\n  theme: Ref\u003CTheme>\n  toggleTheme: () => void\n}> = Symbol('theme')\n\nexport function provideTheme(initialTheme: Theme = 'light') {\n  const theme = ref\u003CTheme>(initialTheme)\n  const toggleTheme = () => {\n    theme.value = theme.value === 'light' ? 'dark' : 'light'\n  }\n  provide(ThemeKey, { theme: readonly(theme), toggleTheme })\n  return { theme, toggleTheme }\n}\n\nexport function useTheme() {\n  const context = inject(ThemeKey)\n  if (!context) throw new Error('useTheme must be used within provideTheme')\n  return context\n}\n\n\u002F\u002F In root component\nprovideTheme()\n\n\u002F\u002F In any descendant\nconst { theme, toggleTheme } = useTheme()\n```\n\n## Advanced Notes\nProvide\u002FInject works with **app-level provide**: `app.provide('key', value)` makes the value available to all components. This is how plugins like Vue Router provide `$route` and `$router`. Also, you can provide a `computed` value for derived reactive state.",[218,219,81,203],"provide-inject","dependency-injection",{"id":57,"category":221,"question":222,"answer":223,"level":179,"tags":224},"Rendering","What are async components and Suspense? How to use them for code splitting and loading states?","## Core Concept\n- **Async components** are components that are loaded lazily (code splitting). `defineAsyncComponent` creates a component that fetches its implementation only when needed.\n- **Suspense** is a built-in component that orchestrates async dependencies (async components or components with async `setup()`). It shows a fallback content while async operations are pending.\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { defineAsyncComponent } from 'vue'\n\n\u002F\u002F Basic async component\nconst AsyncModal = defineAsyncComponent(() => import('.\u002FModal.vue'))\n\n\u002F\u002F With loading\u002Ferror states\nconst AsyncDashboard = defineAsyncComponent({\n  loader: () => import('.\u002FDashboard.vue'),\n  loadingComponent: LoadingSpinner,\n  errorComponent: ErrorDisplay,\n  delay: 200,          \u002F\u002F delay before showing loading component\n  timeout: 3000        \u002F\u002F timeout for error component\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003C!-- Suspense with async component -->\n  \u003CSuspense>\n    \u003Ctemplate #default>\n      \u003CAsyncDashboard \u002F>\n    \u003C\u002Ftemplate>\n    \u003Ctemplate #fallback>\n      \u003Cdiv>Loading dashboard...\u003C\u002Fdiv>\n    \u003C\u002Ftemplate>\n  \u003C\u002FSuspense>\n\n  \u003C!-- Multiple async children -->\n  \u003CSuspense>\n    \u003Ctemplate #default>\n      \u003CAsyncComments \u002F>\n      \u003CAsyncSidebar \u002F>\n    \u003C\u002Ftemplate>\n    \u003Ctemplate #fallback>\n      \u003CLoadingSpinner \u002F>\n    \u003C\u002Ftemplate>\n  \u003C\u002FSuspense>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. Initial render: Suspense shows fallback content immediately.\n2. Async component starts loading (`import()`).\n3. When all async components inside Suspense are resolved, Suspense triggers default content render.\n4. If an async operation fails, Suspense can emit an error (use `onErrorCaptured`).\n5. Async components are cached after first load – subsequent renders are synchronous.\n\n## Reactivity Explanation\nAsync components are still reactive once loaded. Suspense does not add reactivity; it's a control flow mechanism for asynchronous dependencies.\n\n## Practical Usage\n- **Code splitting**: Route-level lazy loading, large modals, heavy charts.\n- **Suspense**: Component that depends on async data (e.g., `fetch` inside `setup`).\n- **Nested Suspense**: For complex pages with multiple async sections.\n\n## Interview Insight\nExplain that Suspense is still **experimental** but stable in practice. It works best with `async setup()` and async components. Unlike React Suspense, Vue's Suspense also works for any async operation inside the component tree.\n\n## Common Mistakes\n- Using Suspense without any async dependency – it will just render default.\n- Not handling errors – wrap Suspense with an error boundary or use `onErrorCaptured`.\n- Overusing Suspense for simple loading states – `v-if` may be simpler.\n- Forgetting that `defineAsyncComponent` returns a component, not a function.\n\n## Best Practices\n- Use async components for routes, heavy UI pieces, and conditionally loaded features.\n- Set sensible `delay` (to avoid loading flicker) and `timeout` (to handle network issues).\n- Provide a meaningful fallback UI – avoid just \"Loading...\"\n- Combine with `KeepAlive` to cache loaded async components.\n\n## Performance Considerations\n- Async components reduce initial bundle size.\n- Loading too many async components in one Suspense may delay rendering (parallel loading is limited).\n- Use `webpackPrefetch` or Vite's `vite:prefetch` to preload critical async chunks.\n\n## Production Recommendations\n- In Vite, async components automatically benefit from code splitting.\n- Use `defineAsyncComponent` with `loadingComponent` and `errorComponent` for robust UX.\n- For SSR, async components need special handling (they are resolved on server as well).\n\n## Latest Vue Patterns\n- **Top-level await** in `\u003Cscript setup>` – component becomes async automatically, must be wrapped in Suspense.\n- **`\u003CSuspense>` with `onResolve` \u002F `onPending`** events (Vue 3.3+).\n- **Suspense with `fallback` slot** for custom loading.\n\n## Interview Tip\nDiscuss the difference between `defineAsyncComponent` and dynamic `import()` in a computed – the former integrates with Suspense and error handling, the latter does not.\n\n## Common Follow-up\n*\"Can Suspense handle nested async components?\"* – Yes, Suspense waits for the entire tree of async dependencies, not just direct children.\n\n## Real-world Example\nDashboard page with async widgets:\n```vue\n\u003Ctemplate>\n  \u003CSuspense @pending=\"loading = true\" @resolve=\"loading = false\">\n    \u003Ctemplate #default>\n      \u003CAsyncUserStats :userId=\"userId\" \u002F>\n      \u003CAsyncActivityChart \u002F>\n      \u003CAsyncRecentOrders \u002F>\n    \u003C\u002Ftemplate>\n    \u003Ctemplate #fallback>\n      \u003Cdiv class=\"skeleton\">\n        \u003Cdiv class=\"skeleton-card\" v-for=\"i in 3\" :key=\"i\">\u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002Ftemplate>\n  \u003C\u002FSuspense>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { defineAsyncComponent, ref } from 'vue'\n\nconst AsyncUserStats = defineAsyncComponent(() => import('.\u002FUserStats.vue'))\nconst AsyncActivityChart = defineAsyncComponent(() => import('.\u002FActivityChart.vue'))\nconst AsyncRecentOrders = defineAsyncComponent(() => import('.\u002FRecentOrders.vue'), {\n  loadingComponent: () => import('.\u002FSmallSpinner.vue'),\n  delay: 300,\n  timeout: 10000\n})\n\nconst userId = ref(123)\nconst loading = ref(true)\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\nSuspense uses **error boundary** semantics – if any async child rejects, you can catch it with `onErrorCaptured` in a parent. Vue's Suspense does **not** fall back to the fallback on subsequent updates unless you explicitly reset. For refresh, you can use a `key` on the Suspense or force remount. Async components also work with `import()` prefetching: `\u002F* webpackPrefetch: true *\u002F`.",[225,226,227,174],"async-components","suspense","code-splitting",{"id":65,"category":229,"question":230,"answer":231,"level":179,"tags":232},"Performance Optimization","What are virtual scrolling, v-memo, and v-once, and how do they improve performance?","## Core Concept\n- **Virtual scrolling** – technique to render only visible items in a long list, drastically reducing DOM nodes.\n- **`v-memo`** – memoizes a template subtree, re-rendering only when specified dependencies change.\n- **`v-once`** – renders static content only once; never updates.\n\n## Syntax\n```vue\n\u003Ctemplate>\n  \u003C!-- v-once: never changes, good for static content -->\n  \u003Cdiv v-once>\n    \u003Ch1>Static header that never updates\u003C\u002Fh1>\n    \u003Cp>{{ staticContent }}\u003C\u002Fp>\n  \u003C\u002Fdiv>\n\n  \u003C!-- v-memo: re-render only when item.id or selected changes -->\n  \u003Cdiv v-for=\"item in list\" :key=\"item.id\" v-memo=\"[item.id, selected === item.id]\">\n    \u003Cp>{{ item.name }}\u003C\u002Fp>\n    \u003Cp v-if=\"selected === item.id\">Selected!\u003C\u002Fp>\n  \u003C\u002Fdiv>\n\n  \u003C!-- Virtual scrolling with vue-virtual-scroller -->\n  \u003CDynamicScroller :items=\"items\" :min-item-size=\"50\">\n    \u003Ctemplate v-slot=\"{ item, index, active }\">\n      \u003CDynamicScrollerItem :item=\"item\" :active=\"active\" :size-dependencies=\"[item.text]\">\n        \u003Cdiv>{{ item.text }}\u003C\u002Fdiv>\n      \u003C\u002FDynamicScrollerItem>\n    \u003C\u002Ftemplate>\n  \u003C\u002FDynamicScroller>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n**Virtual scrolling:**\n1. Container calculates viewport height and scroll position.\n2. Only items that intersect viewport (plus buffer) are rendered.\n3. As user scrolls, items are swapped in\u002Fout.\n4. DOM node count remains constant (~20x viewport height).\n\n**v-memo:**\n1. During render, Vue evaluates `v-memo` array dependencies.\n2. If all dependencies are equal to previous render, the entire subtree is skipped (no diffing).\n3. If any dependency changed, subtree re-renders normally.\n\n**v-once:**\n1. On first render, Vue caches the generated VNodes.\n2. All future renders reuse the cached VNodes – no re-evaluation.\n\n## Reactivity Explanation\nThese directives skip reactivity in different ways: `v-once` never reacts; `v-memo` reacts only to listed dependencies; virtual scrolling doesn't skip reactivity but reduces DOM footprint.\n\n## Practical Usage\n- **Virtual scrolling**: Infinite scroll feeds, large data tables (>2000 items), chat logs.\n- **v-memo**: Large lists with stable items and rare selection changes, expensive components with few changing props.\n- **v-once**: Static hero sections, logos, copyright footers, static SVGs.\n\n## Interview Insight\nExplain that Vue 3's diffing is fast, but virtual scrolling is essential for huge lists. `v-memo` is often overlooked – it can significantly cut render time for lists with per-item state (e.g., selected, expanded).\n\n## Common Mistakes\n- Overusing `v-memo` with empty array – causes never update (unless intended).\n- Using `v-once` on content that should update occasionally – leads to stale UI.\n- Implementing custom virtual scrolling badly (layout shifts, accessibility issues).\n- Not providing `:key` when using `v-memo` – memoization may misbehave.\n\n## Best Practices\n- Use virtual scrolling libraries (`vue-virtual-scroller`, `@tanstack\u002Fvirtual`).\n- Use `v-memo` only on expensive, stable sublists measured by profiler.\n- Use `v-once` for truly static content (no dynamic bindings inside).\n- Combine `v-memo` with `key` attribute on loop items.\n\n## Performance Considerations\n- Virtual scrolling reduces initial render time from O(n) to O(viewport).\n- `v-memo` can skip entire subtree diff, saving CPU on every re-render.\n- `v-once` reduces memory and CPU, but too many cached VNodes may increase memory.\n\n## Production Recommendations\n- For tables with >1000 rows, virtual scroll is mandatory.\n- Profile with Vue DevTools to identify re-render bottlenecks before using `v-memo`.\n- Use `v-once` on static parts of templates that have many DOM nodes.\n\n## Latest Vue Patterns\n- **`@tanstack\u002Fvue-virtual`** – modern headless virtual scrolling library.\n- **`v-memo` with arrays** – you can pass any reactive values.\n- **`v-once` with `v-html`** – render static sanitized HTML once.\n\n## Interview Tip\nAsk the interviewer: “Do you need to maintain scroll position with virtual scrolling?” That’s a challenge – you may need `scrollRestoration` or caching.\n\n## Common Follow-up\n*\"Can v-memo work with v-for?\"* – Yes, but the memo dependencies must be per-item. Use `v-memo=\"[item.id, item.selected]\"` inside the loop.\n\n## Real-world Example\nLarge selectable list with `v-memo`:\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cinput v-model=\"search\" placeholder=\"Filter\">\n    \u003Cul>\n      \u003Cli\n        v-for=\"item in filteredList\"\n        :key=\"item.id\"\n        v-memo=\"[item.id, selectedId === item.id]\"\n        @click=\"selectItem(item.id)\"\n        :class=\"{ selected: selectedId === item.id }\"\n      >\n        \u003Cstrong>{{ item.name }}\u003C\u002Fstrong>\n        \u003Cspan v-if=\"selectedId === item.id\">✓\u003C\u002Fspan>\n      \u003C\u002Fli>\n    \u003C\u002Ful>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { ref, computed } from 'vue'\nconst items = ref(Array.from({ length: 5000 }, (_, i) => ({ id: i, name: `Item ${i}` })))\nconst search = ref('')\nconst selectedId = ref(null)\n\nconst filteredList = computed(() => \n  items.value.filter(i => i.name.includes(search.value))\n)\n\nfunction selectItem(id) {\n  selectedId.value = id\n}\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\nVirtual scrolling libraries often need `min-item-size` for accurate scrollbar calculation. For dynamic heights, use `DynamicScroller` (vue-virtual-scroller). `v-memo` is implemented via a `memo` option in the VNode, causing the patching algorithm to skip the node. It's most effective when the memoized subtree has many static children or expensive render functions.",[233,234,235,183,236],"virtual-scroll","v-memo","v-once","lists",{"id":74,"category":238,"question":239,"answer":240,"level":179,"tags":241},"TypeScript","How to use TypeScript with Vue 3 components, props, emits, and composables?","## Core Concept\nVue 3 has first-class TypeScript support. With `\u003Cscript setup lang=\"ts\">`, you can type props, emits, slots, refs, and composables with full inference. Use `defineProps`, `defineEmits`, `defineSlots` with type arguments.\n\n## Syntax\n```vue\n\u003Cscript setup lang=\"ts\">\nimport { ref, computed, type Ref } from 'vue'\n\n\u002F\u002F Typed props with defaults\ninterface Props {\n  title: string\n  count?: number\n  user: { id: number; name: string }\n}\nconst props = withDefaults(defineProps\u003CProps>(), {\n  count: 0\n})\n\n\u002F\u002F Typed emits\nconst emit = defineEmits\u003C{\n  (e: 'update', value: number): void\n  (e: 'delete', id: number): void\n}>()\n\n\u002F\u002F Typed refs\nconst count = ref\u003Cnumber>(0)\nconst user = ref\u003CUser | null>(null)\n\n\u002F\u002F Computed with explicit return type\nconst double = computed\u003Cnumber>(() => count.value * 2)\n\n\u002F\u002F Template refs\nconst inputRef = ref\u003CHTMLInputElement | null>(null)\n\n\u002F\u002F Typed slots\ndefineSlots\u003C{\n  default(props: { msg: string }): any\n  header(): any\n}>()\n\n\u002F\u002F defineModel with type\nconst modelValue = defineModel\u003Cstring>()\n\u003C\u002Fscript>\n```\n\n## Execution Flow\nTypeScript types are stripped at compile time. Vue's compiler uses them to generate correct runtime prop validation and provide IDE intellisense. No runtime overhead.\n\n## Reactivity Explanation\nTypes do not affect reactivity. However, typing refs as `Ref\u003CT>` helps prevent incorrect mutations (e.g., forgetting `.value`).\n\n## Practical Usage\n- Large applications with multiple developers\n- Component libraries (better API documentation)\n- Refactoring and catching bugs early\n- Using external typed libraries (Pinia, Vue Router)\n\n## Interview Insight\nExplain that Vue 3's TypeScript support is **compile-time only** for SFCs. Types are not validated at runtime unless you use `withDefaults` or runtime checks. `defineProps` with type-only syntax requires `vue-tsc` for type checking.\n\n## Common Mistakes\n- Using `defineProps` without `lang=\"ts\"` (works but no type inference).\n- Forgetting `withDefaults` for optional props with default values.\n- Typing `ref` as `Ref\u003CType>` instead of `ref\u003CType>()`.\n- Not providing proper types for `computed` when return type could be ambiguous.\n\n## Best Practices\n- Use `interface` for props; `type` for complex unions.\n- Use `withDefaults` for default prop values.\n- Use `vue-tsc` for type checking in CI.\n- Export types\u002Finterfaces that are reused across components.\n- Use `InstanceType\u003Ctypeof MyComponent>` to get component instance type for refs.\n\n## Performance Considerations\nTypeScript adds build-time overhead but no runtime cost. Use `vue-tsc --noEmit` for checking.\n\n## Production Recommendations\n- Configure `tsconfig.json` with `\"strict\": true`.\n- Use `@vue\u002Ftsconfig` for recommended settings.\n- In monorepos, use `vue-tsc` to type-check SFCs.\n\n## Latest Vue Patterns\n- **Generic components** with `defineProps\u003C{ item: T }>()` and `defineGeneric` (Vue 3.3+).\n- **`defineSlots`** for typed slots.\n- **`defineEmits` with tuple syntax**: `defineEmits\u003C{ update: [value: number] }>()` (Vue 3.3+).\n- **`useTemplateRef`** for typed template refs (Vue 3.5+).\n\n## Interview Tip\nShow that `defineProps\u003C{ msg: string }>()` is compile-time only; to get runtime validation, you need the runtime syntax: `defineProps({ msg: String })`. For hybrid, use `withDefaults`.\n\n## Common Follow-up\n*\"How do you type a composable that accepts a ref or plain value?\"* – Use `MaybeRef\u003CT>` or `MaybeRefOrGetter\u003CT>` from `@vueuse\u002Fcore` or Vue 3.3 `toValue`.\n\n## Real-world Example\nGeneric list component with typed slots:\n```vue\n\u003Cscript setup lang=\"ts\" generic=\"T\">\nimport { ref } from 'vue'\n\ninterface Props {\n  items: T[]\n  keyField: keyof T\n}\n\nconst props = defineProps\u003CProps>()\nconst emit = defineEmits\u003C{\n  (e: 'select', item: T): void\n}>()\n\n\u002F\u002F Slot types\ndefineSlots\u003C{\n  default(props: { item: T; index: number }): any\n  header(): any\n}>()\n\nconst selectedIndex = ref\u003Cnumber | null>(null)\nfunction select(idx: number) {\n  selectedIndex.value = idx\n  emit('select', props.items[idx])\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cslot name=\"header\" \u002F>\n    \u003Cdiv\n      v-for=\"(item, idx) in items\"\n      :key=\"String(item[keyField])\"\n      @click=\"select(idx)\"\n      :class=\"{ selected: selectedIndex === idx }\"\n    >\n      \u003Cslot :item=\"item\" :index=\"idx\">\n        {{ String(item[keyField]) }}\n      \u003C\u002Fslot>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nVue's TypeScript support relies on `vue-tsc` for SFC type checking. The compiler also generates `.d.ts` files for component types when building libraries. Use `global.d.ts` to augment Vue types (e.g., custom component props). For complex generic components, use `generic` attribute on `\u003Cscript setup>`.",[203,88,89,201,242],"typing",{"id":83,"category":157,"question":244,"answer":245,"level":179,"tags":246},"What is Pinia architecture: stores, state, getters, actions, and how to organise them at scale?","## Core Concept\nPinia is the official state management library. Each store is a module containing **state** (reactive data), **getters** (computed values), and **actions** (methods that can be async and mutate state). Stores can reference each other, support hot module replacement, and work with both Options and Composition API.\n\n## Syntax\n```ts\n\u002F\u002F stores\u002Fuser.ts – Composition API style (recommended)\nimport { defineStore } from 'pinia'\nimport { ref, computed } from 'vue'\nimport { useCartStore } from '.\u002Fcart'\n\nexport const useUserStore = defineStore('user', () => {\n  \u002F\u002F state\n  const user = ref\u003C{ id: number; name: string } | null>(null)\n  const token = ref(localStorage.getItem('token'))\n\n  \u002F\u002F getters\n  const isLoggedIn = computed(() => !!token.value)\n  const displayName = computed(() => user.value?.name ?? 'Guest')\n\n  \u002F\u002F actions\n  async function login(email: string, password: string) {\n    const response = await api.post('\u002Flogin', { email, password })\n    user.value = response.data.user\n    token.value = response.data.token\n    localStorage.setItem('token', token.value)\n  }\n\n  function logout() {\n    user.value = null\n    token.value = null\n    localStorage.removeItem('token')\n    \u002F\u002F call another store's action\n    const cartStore = useCartStore()\n    cartStore.clearCart()\n  }\n\n  return { user, token, isLoggedIn, displayName, login, logout }\n})\n```\n\n## Execution Flow\n1. `defineStore` creates a store factory. First call to `useUserStore()` creates the store instance (singleton).\n2. State is reactive; components using store subscribe to changes.\n3. Getters are cached computed values, recomputed when dependencies change.\n4. Actions can be async; they directly mutate state (no mutations like Vuex).\n5. Stores can import each other – circular references handled automatically.\n\n## Reactivity Explanation\nPinia uses Vue's `ref` and `reactive` internally. State returned from store is reactive; `storeToRefs` helps destructure while preserving reactivity. Actions are plain functions, not reactive.\n\n## Practical Usage\n- Global app state (auth, theme, notifications)\n- Domain-specific stores (user, products, cart, orders)\n- Cross-store communication (e.g., cart clears on logout)\n\n## Interview Insight\nExplain that Pinia replaces Vuex. Key differences: no mutations, better TypeScript, multiple stores (not a single tree), and automatic code splitting. Pinia stores are more flexible and have a smaller API surface.\n\n## Common Mistakes\n- Destructuring store without `storeToRefs` (loses reactivity).\n- Mutating state outside actions (works but breaks devtools tracking).\n- Not using `$reset()` – manually resetting each property is error-prone.\n- Creating circular store dependencies incorrectly (Pinia allows it, but be careful with infinite loops).\n\n## Best Practices\n- Use Composition API style stores for better TypeScript inference.\n- Keep state flat – avoid deep nesting; use normalisation.\n- Use `store.$patch` for batch updates.\n- Organise stores by domain in `\u002Fstores` directory.\n- Use `store.$onAction` for logging or analytics.\n\n## Performance Considerations\n- Pinia is lightweight; stores are lazy-initialised.\n- Too many getters can cause recalculation; memoise expensive ones manually.\n- Avoid storing large non-reactive data in state; use `shallowRef`.\n\n## Production Recommendations\n- Use `pinia-plugin-persistedstate` to persist state to localStorage.\n- For SSR, use `createPinia()` and `pinia.state.value` for hydration.\n- Use `store.$subscribe` to react to state changes for persistence or logs.\n\n## Latest Vue Patterns\n- **`mapStores`** helper for Options API (legacy).\n- **`store.$onAction`** for middleware.\n- **Hot module replacement** – stores can be replaced without reload.\n\n## Interview Tip\nMention that Pinia has **no modules** like Vuex – each store is a module. You create separate stores (e.g., `useUserStore`, `useCartStore`) and import them as needed. This enables better code splitting.\n\n## Common Follow-up\n*\"How do you reset a Pinia store to its initial state?\"* – Use `store.$reset()` for Options API stores; for setup stores, you need to implement your own reset function.\n\n## Real-world Example\nModular e-commerce store organisation:\n```ts\n\u002F\u002F stores\u002Findex.ts – central export\nexport { useUserStore } from '.\u002Fuser'\nexport { useCartStore } from '.\u002Fcart'\nexport { useProductStore } from '.\u002Fproduct'\n\n\u002F\u002F stores\u002Fcart.ts\nimport { defineStore } from 'pinia'\nimport { ref, computed } from 'vue'\nimport { useUserStore } from '.\u002Fuser'\n\nexport const useCartStore = defineStore('cart', () => {\n  const items = ref\u003CArray\u003C{ id: number; qty: number }>>([])\n  const totalItems = computed(() => items.value.reduce((sum, i) => sum + i.qty, 0))\n  \n  function addItem(id: number) {\n    const existing = items.value.find(i => i.id === id)\n    if (existing) existing.qty++\n    else items.value.push({ id, qty: 1 })\n  }\n  \n  function clearCart() {\n    items.value = []\n  }\n  \n  return { items, totalItems, addItem, clearCart }\n})\n\n\u002F\u002F Component usage\n\u003Cscript setup>\nimport { storeToRefs } from 'pinia'\nimport { useCartStore, useUserStore } from '@\u002Fstores'\n\nconst cart = useCartStore()\nconst { totalItems } = storeToRefs(cart)\nconst { isLoggedIn } = storeToRefs(useUserStore())\n\nfunction checkout() {\n  if (!isLoggedIn.value) router.push('\u002Flogin')\n  else cart.clearCart()\n}\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\nPinia supports **plugins** to add global functionality (e.g., persistent storage, loading states). `store.$patch` can accept a function for complex mutations. For large apps, use `defineStore` with `id` and separate state\u002Fgetters\u002Factions objects to enable HMR. Pinia devtools integration shows mutations timeline and time travel.",[161,162,163,13],{"id":93,"category":122,"question":248,"answer":249,"level":179,"tags":250},"How does computed property caching work internally? When does it recompute?","## Core Concept\nComputed properties are **lazy, cached reactive values**. Internally, each computed creates a `ComputedRefImpl` that holds a cached result and a `_dirty` flag. The getter runs only when the computed is read and marked dirty. Dependencies are tracked via Vue's effect system.\n\n**Recomputation conditions:**\n- A reactive dependency (ref, reactive, other computed) changes.\n- The computed is read after the change (lazy – not eager).\n- If multiple dependencies change, computed re-runs only once before next read.\n\n## Syntax\n```ts\nimport { computed, ref, effectScope } from 'vue'\n\nconst count = ref(0)\nconst double = computed(() => count.value * 2)\n\u002F\u002F Internally: _dirty = true initially\n\nconsole.log(double.value) \u002F\u002F runs getter, caches 0, _dirty = false\ncount.value = 2           \u002F\u002F notifies computed, _dirty = true\nconsole.log(double.value) \u002F\u002F re-runs getter (count.value now 2), caches 4\n```\n\n## Execution Flow\n1. When computed is created, it creates a reactive effect but **does not run** immediately.\n2. First read triggers the getter, collects dependencies (e.g., `count.value`), stores result, sets `_dirty = false`.\n3. When a dependency updates, the computed's effect is triggered, which only flips `_dirty = true` (does not recompute yet).\n4. Next read sees `_dirty === true`, re-runs getter, caches new result, sets `_dirty = false`.\n5. If computed is never read after dependency changes, it never recomputes – lazy evaluation.\n\n## Reactivity Explanation\nThe computed uses Vue's `effect` (like `watchEffect`) but with `lazy: true` and `scheduler` that only marks dirty instead of re-executing. This prevents unnecessary recalculations.\n\n## Practical Usage\n- Derived state that is expensive to compute (filtering large arrays).\n- Formatting dates, currencies, units.\n- Validating form fields based on multiple inputs.\n\n## Interview Insight\nExplain that computed **caches per instance** and is **lazy** – different from React's `useMemo` which runs on every render but memoizes result. Vue's computed also has better granularity: dependencies tracked automatically.\n\n## Common Mistakes\n- Creating side effects inside computed (e.g., API calls, DOM updates) – computed should be pure.\n- Assuming computed runs immediately when dependency changes (it doesn't until read).\n- Using computed for values that change on every read (e.g., `Date.now()`) – it will never update.\n\n## Best Practices\n- Keep computed getters fast and side-effect free.\n- For expensive computed that depend on rarely changed data, it's fine.\n- Use `computed({ get, set })` for writable computed.\n\n## Performance Considerations\n- Cached computed reduces re-renders: if computed result hasn't changed, consuming components may skip render.\n- Avoid returning new objects\u002Farrays each time unless necessary (causes child re-renders).\n\n## Production Recommendations\n- In large lists, computed with `.filter().map()` is fine for up to ~10k items. Beyond that, consider web workers or virtual scrolling.\n- Use `shallowRef` inside computed if returning large data that won't be mutated deeply.\n\n## Latest Vue Patterns\n- **`computed` with `shallow` option** (Vue 3.4+) – returns shallow ref, useful for large computed results.\n- **`toValue`** inside computed to unwrap refs or getters.\n\n## Interview Tip\nCompare computed vs method: computed caches; method re-runs on every render. Show an example where a method in `v-for` causes massive slowdown.\n\n## Common Follow-up\n*\"Can a computed depend on another computed?\"* – Yes, chain works. The dependent computed will re-run only when its own dependencies change, and the chain is lazy.\n\n## Real-world Example\nExpensive filtered list with search and sort:\n```ts\nconst items = ref(Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `Item ${i}` })))\nconst search = ref('')\nconst sortDirection = ref\u003C'asc' | 'desc'>('asc')\n\nconst filteredAndSorted = computed(() => {\n  \u002F\u002F This runs only when items, search, or sortDirection change\n  let result = items.value.filter(item => item.name.includes(search.value))\n  result.sort((a, b) => sortDirection.value === 'asc' ? a.id - b.id : b.id - a.id)\n  return result\n})\n```\n\n## Advanced Notes\nInternally, `ComputedRefImpl` extends `Ref`. The effect scheduler uses `triggerRefValue` to mark dirty. Vue also optimizes computed for SSR – on server, computed are eagerly evaluated to support streaming.",[78,213,81,251],"internals",{"id":103,"category":7,"question":253,"answer":254,"level":179,"tags":255},"What is nextTick and when should you use it?","## Core Concept\n`nextTick` is a utility that defers a callback to be executed after the next DOM update cycle. Vue batches reactive updates and updates the DOM asynchronously. `nextTick` allows you to wait for the DOM to reflect the latest state changes before running code.\n\n## Syntax\n```vue\n\u003Cscript setup>\nimport { ref, nextTick } from 'vue'\n\nconst count = ref(0)\nconst message = ref('')\nconst inputRef = ref\u003CHTMLInputElement>()\n\nasync function increment() {\n  count.value++\n  \u002F\u002F DOM not updated yet\n  console.log(inputRef.value?.textContent) \u002F\u002F old value\n\n  await nextTick()\n  \u002F\u002F DOM now updated\n  console.log(inputRef.value?.textContent) \u002F\u002F new value\n  inputRef.value?.focus()\n}\n\n\u002F\u002F Alternative callback style\nnextTick(() => {\n  console.log('DOM updated')\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv ref=\"inputRef\">{{ count }}\u003C\u002Fdiv>\n  \u003Cbutton @click=\"increment\">+1\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. You modify reactive state (e.g., `count.value++`).\n2. Vue schedules a microtask to flush pending effects (update DOM).\n3. Any synchronous code continues running – DOM is stale.\n4. `nextTick` adds a callback to be executed after the flush queue.\n5. When the microtask runs, DOM updates, then your callback runs.\n\n## Reactivity Explanation\n`nextTick` doesn't affect reactivity; it just waits for the scheduler. Internally, Vue uses `Promise.resolve().then()` (or `setImmediate` fallback) to queue the callback.\n\n## Practical Usage\n- Accessing updated DOM after state change (e.g., focus input, measure element size).\n- Waiting for child component to re-render before calling its exposed method.\n- Ensuring a component is mounted before interacting with it in tests.\n- Synchronizing with third-party libraries that read DOM properties.\n\n## Interview Insight\nExplain Vue's **asynchronous DOM updates** – it batches changes for performance. `nextTick` is the bridge between state mutation and DOM reading. Without it, you may read stale DOM.\n\n## Common Mistakes\n- Using `nextTick` unnecessarily (most code doesn't need it).\n- Forgetting `await` when using `nextTick` in async function (callback still works, but order may be wrong).\n- Assuming `nextTick` guarantees child component has finished its own async updates (it waits for current tick only).\n\n## Best Practices\n- Use `nextTick` only when you need to read computed DOM properties.\n- Prefer `watchPostEffect` for DOM-related side effects (more declarative).\n- In tests, use `await nextTick()` or `await flushPromises()` after state updates.\n\n## Performance Considerations\n`nextTick` adds one microtask delay – negligible. Overusing `nextTick` in loops can degrade performance; batch DOM reads instead.\n\n## Production Recommendations\n- For complex animations, use `nextTick` with `requestAnimationFrame`.\n- In Vue Router, `nextTick` is not needed for `onMounted` – mounted already waits for initial render.\n\n## Latest Vue Patterns\n- **`nextTick` with `flush: 'post'`** – same as `watchPostEffect`.\n- **`nextTick` inside composables** to wait for DOM after state change.\n\n## Interview Tip\nMention that Vue's `nextTick` is similar to React's `setTimeout` + flushSync, but more reliable. Also note that in Vue 2, `this.$nextTick` was attached to instance; in Vue 3, you import the function.\n\n## Common Follow-up\n*\"What is the difference between `nextTick` and `setTimeout`?\"* – `nextTick` uses microtasks (higher priority), `setTimeout` uses macrotasks. `nextTick` runs before any `setTimeout` queued in the same event loop.\n\n## Real-world Example\nAuto-expanding textarea height after content change:\n```vue\n\u003Cscript setup>\nimport { ref, nextTick } from 'vue'\n\nconst text = ref('')\nconst textareaRef = ref\u003CHTMLTextAreaElement>()\n\nasync function adjustHeight() {\n  await nextTick()\n  if (textareaRef.value) {\n    textareaRef.value.style.height = 'auto'\n    textareaRef.value.style.height = `${textareaRef.value.scrollHeight}px`\n  }\n}\n\nwatch(text, () => adjustHeight())\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Ctextarea ref=\"textareaRef\" v-model=\"text\">\u003C\u002Ftextarea>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\n`nextTick` can be used to flatten multiple updates: if you call `nextTick` multiple times with callbacks, they all run after the same DOM update. Internally, Vue uses a queue of job queues; `nextTick` adds to the post-flush queue. For advanced use, `flushPost` effects are essentially `nextTick` under the hood.",[256,257,152,258],"nextTick","dom-updates","scheduler",{"id":112,"category":94,"question":260,"answer":261,"level":179,"tags":262},"Explain the lifecycle internals: how Vue manages component creation, update, and destruction under the hood.","## Core Concept\nVue components go through a lifecycle: create → mount → update → unmount. Internally, each stage involves setting up reactivity, compiling templates (or using render functions), creating VNodes, patching the DOM, and cleaning up effects.\n\n**Key internal phases:**\n1. **Initialization:** `setup()` runs, creates reactive state, effects, and computed.\n2. **Render:** Render function produces VNode tree.\n3. **Mount:** VNode tree is patched into real DOM (using `render` function).\n4. **Update:** Reactive change triggers scheduler, re-render, diff, patch.\n5. **Unmount:** Effects stopped, DOM removed, cleanup hooks run.\n\n## Execution Flow (Simplified)\n```js\n\u002F\u002F Pseudocode internal logic\nfunction mountComponent(component, container) {\n  const instance = createComponentInstance(component)\n  setupComponent(instance)  \u002F\u002F executes setup(), initializes props\u002Fslots\n  setupRenderEffect(instance) \u002F\u002F creates reactive effect for render\n  \u002F\u002F effect runs: instance.render() → VNode → patch(container, VNode)\n}\n\nfunction setupRenderEffect(instance) {\n  const componentUpdateFn = () => {\n    if (!instance.isMounted) {\n      \u002F\u002F beforeMount hook\n      const subTree = instance.render()\n      patch(null, subTree, instance.container)\n      instance.isMounted = true\n      \u002F\u002F mounted hook\n    } else {\n      \u002F\u002F beforeUpdate hook\n      const prevTree = instance.subTree\n      const nextTree = instance.render()\n      patch(prevTree, nextTree, instance.container)\n      \u002F\u002F updated hook\n    }\n  }\n  const effect = new ReactiveEffect(componentUpdateFn, () => queueJob(effect))\n  instance.effect = effect\n}\n```\n\n## Reactivity Explanation\nThe render effect tracks all reactive dependencies used during render. When any dependency changes, the scheduler queues a re-run of the render effect, leading to DOM patch.\n\n## Practical Usage\n- Understanding lifecycles helps debug why certain code runs at wrong times.\n- Using `onMounted` for DOM access, `onUnmounted` for cleanup, `onErrorCaptured` for error boundaries.\n\n## Interview Insight\nExplain that `setup()` runs before the component instance is fully created – no `this` access. Lifecycle hooks registered in `setup` are attached to the instance and called at the right times. This is different from Vue 2 where hooks were options.\n\n## Common Mistakes\n- Assuming DOM is ready in `setup()` or `onBeforeMount`.\n- Forgetting that `onUpdated` runs after every re-render, which can cause infinite loops if you mutate state there.\n- Not cleaning up side effects in `onUnmounted`.\n\n## Best Practices\n- Use `onMounted` for initial data fetching (not `setup` except for SSR).\n- Keep `onUpdated` light – avoid state changes.\n- Use `onErrorCaptured` for component-level error handling.\n\n## Performance Considerations\n- Lifecycle hooks are cheap, but `onUpdated` may fire often – defer heavy work.\n- `onUnmounted` cleanup prevents memory leaks (e.g., event listeners, intervals).\n\n## Production Recommendations\n- In large apps, use `onActivated`\u002F`onDeactivated` for cached components (`KeepAlive`).\n- Use `onServerPrefetch` for SSR data fetching.\n\n## Latest Vue Patterns\n- **`onWatcherCleanup`** (Vue 3.5) – cleanup for async watchers.\n- **`onEffectCleanup`** – for custom effects.\n\n## Interview Tip\nAsk about the order: `onBeforeMount` → DOM created → `onMounted`. Also note that `onBeforeUpdate` runs before the DOM is patched, so DOM reads there may be stale. Use `nextTick` or `watchPostEffect` for updated DOM.\n\n## Common Follow-up\n*\"What happens if you call `onMounted` inside a composable?\"* – It is attached to the calling component. Works as expected.\n\n## Real-world Example\nTracking component visibility with intersection observer:\n```vue\n\u003Cscript setup>\nimport { ref, onMounted, onUnmounted } from 'vue'\nconst el = ref\u003CHTMLElement>()\nlet observer: IntersectionObserver | null = null\n\nonMounted(() => {\n  observer = new IntersectionObserver(([entry]) => {\n    console.log('visible', entry.isIntersecting)\n  })\n  if (el.value) observer.observe(el.value)\n})\n\nonUnmounted(() => observer?.disconnect())\n\u003C\u002Fscript>\n\u003Ctemplate>\u003Cdiv ref=\"el\">Watch me\u003C\u002Fdiv>\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nVue's scheduler distinguishes between component update queue and post-flush queue (for `watchPostEffect`). Lifecycle hooks like `onUpdated` are scheduled after render but before nextTick. The `instance.isMounted` flag prevents re-running mount hooks. For error handling, `onErrorCaptured` can stop propagation by returning `false`.",[98,251,263,264],"mounting","updating",{"id":121,"category":137,"question":266,"answer":267,"level":179,"tags":268},"What are advanced Vue Router patterns: route guards, meta fields, lazy loading, and navigation failures?","## Core Concept\nAdvanced routing includes **navigation guards** (global, per-route, in-component), **route meta fields** for metadata, **lazy loading** for code splitting, and handling **navigation failures** (e.g., cancelled, redirected).\n\n## Syntax\n```js\n\u002F\u002F router\u002Findex.js\nimport { createRouter, createWebHistory } from 'vue-router'\n\nconst router = createRouter({\n  history: createWebHistory(),\n  routes: [\n    {\n      path: '\u002Fdashboard',\n      component: () => import('.\u002Fviews\u002FDashboard.vue'), \u002F\u002F lazy\n      meta: { requiresAuth: true, roles: ['admin', 'user'] }\n    },\n    {\n      path: '\u002Fadmin',\n      component: () => import('.\u002Fviews\u002FAdmin.vue'),\n      meta: { requiresAuth: true, roles: ['admin'] }\n    }\n  ]\n})\n\n\u002F\u002F Global before guard\nrouter.beforeEach(async (to, from, next) => {\n  const authStore = useAuthStore()\n  if (to.meta.requiresAuth && !authStore.isLoggedIn) {\n    next({ name: 'login', query: { redirect: to.fullPath } })\n  } else if (to.meta.roles && !to.meta.roles.includes(authStore.role)) {\n    next({ name: 'forbidden' })\n  } else {\n    next()\n  }\n})\n\n\u002F\u002F Global after hook (no next)\nrouter.afterEach((to, from, failure) => {\n  if (failure) console.error('Navigation failed', failure)\n})\n\n\u002F\u002F In-component guard (Composition API)\nimport { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'\nonBeforeRouteLeave((to, from, next) => {\n  if (hasUnsavedChanges.value) {\n    const answer = confirm('Leave without saving?')\n    next(answer)\n  } else next()\n})\n\n\u002F\u002F Handling navigation failures\nconst pushResult = await router.push('\u002Fadmin')\nif (pushResult === false) {\n  \u002F\u002F navigation cancelled\n} else if (pushResult instanceof Error) {\n  console.error(pushResult)\n}\n```\n\n## Execution Flow\n1. `router.push()` triggers navigation.\n2. Global `beforeEach` guards run in order.\n3. Route-level `beforeEnter` guards run.\n4. In-component `beforeRouteUpdate` (if component reused) or `beforeRouteLeave`.\n5. Async components are resolved.\n6. Global `beforeResolve` runs.\n7. Navigation confirmed, update URL, render new component.\n8. Global `afterEach` runs.\n\n## Practical Usage\n- Authentication and authorization.\n- Loading indicators (show loader before route resolves).\n- Analytics tracking (afterEach).\n- Unsaved changes warning (beforeRouteLeave).\n- Lazy loading heavy views.\n\n## Interview Insight\nExplain that navigation guards can be async and return a promise. `next` is optional – you can return a route location instead. In Vue Router 4, `next` is still supported but deprecated in favor of returning values.\n\n## Common Mistakes\n- Forgetting `next()` in global guard – navigation stalls.\n- Using `next('\u002Flogin')` without returning – duplicates guards.\n- Not handling navigation failures (e.g., user tries to leave page with unsaved changes).\n- Placing meta fields incorrectly (outside route object).\n\n## Best Practices\n- Prefer returning a route location over calling `next`.\n- Use `meta` for role\u002Fpermission data.\n- Lazy load all route components.\n- Use `router.isReady()` before mounting app in SSR.\n- Handle navigation failures with `catch` or check return value.\n\n## Performance Considerations\n- Lazy loading reduces initial bundle size.\n- Too many global guards can slow down navigation; keep them fast.\n- Async guards with heavy operations should show loading state.\n\n## Production Recommendations\n- Combine with Pinia for auth state.\n- Use `router.beforeResolve` for data fetching (alternative to per-route).\n- Implement scroll behavior restoration: `scrollBehavior(to, from, savedPosition)`.\n\n## Latest Vue Patterns\n- **Composition API guards** – `onBeforeRouteLeave`, `onBeforeRouteUpdate`.\n- **`router.push` returns Promise** – can be awaited.\n- **Dynamic routing** – `router.addRoute()` for runtime routes.\n\n## Interview Tip\nExplain the difference between `beforeEnter` (route-specific) and `beforeEach` (global). Also note that `beforeRouteUpdate` is called when the same component is reused with different params (e.g., `\u002Fuser\u002F1` to `\u002Fuser\u002F2`).\n\n## Common Follow-up\n*\"How do you prevent navigation with unsaved changes?\"* – Use `onBeforeRouteLeave` with a confirm dialog, and call `next(false)` to cancel.\n\n## Real-world Example\nAuth guard with role-based access:\n```js\nrouter.beforeEach(async (to, from) => {\n  const auth = useAuthStore()\n  if (to.meta.requiresAuth) {\n    if (!auth.isLoggedIn) return { name: 'login', query: { redirect: to.fullPath } }\n    if (to.meta.roles && !to.meta.roles.includes(auth.user.role)) {\n      return { name: 'forbidden' }\n    }\n  }\n  return true\n})\n```\n\n## Advanced Notes\nNavigation failures are objects with `type` property: `NavigationFailureType.aborted`, `redirected`, `cancelled`. Use `isNavigationFailure` helper. For server-side rendering, guards run on server and client; ensure idempotent. Dynamic routes can be added\u002Fremoved at runtime, useful for plugin architectures.",[142,269,270,174,144],"guards","meta",{"id":129,"category":221,"question":272,"answer":273,"level":179,"tags":274},"How to use transition and animation systems in Vue: Transition, TransitionGroup, and JavaScript hooks?","## Core Concept\nVue provides `\u003CTransition>` for single element\u002Fcomponent enter\u002Fleave animations, and `\u003CTransitionGroup>` for list animations. Both apply CSS classes at specific lifecycle stages or trigger JavaScript hooks for custom animations.\n\n## Syntax\n```vue\n\u003Ctemplate>\n  \u003C!-- Basic CSS transition -->\n  \u003CTransition name=\"fade\" mode=\"out-in\">\n    \u003Cdiv v-if=\"show\">Hello\u003C\u002Fdiv>\n  \u003C\u002FTransition>\n\n  \u003C!-- TransitionGroup for list -->\n  \u003CTransitionGroup name=\"list\" tag=\"ul\">\n    \u003Cli v-for=\"item in items\" :key=\"item.id\">{{ item.text }}\u003C\u002Fli>\n  \u003C\u002FTransitionGroup>\n\n  \u003C!-- JavaScript hooks -->\n  \u003CTransition\n    @before-enter=\"beforeEnter\"\n    @enter=\"enter\"\n    @after-enter=\"afterEnter\"\n    @before-leave=\"beforeLeave\"\n    @leave=\"leave\"\n    @after-leave=\"afterLeave\"\n  >\n    \u003Cdiv v-if=\"show\">Animated with JS\u003C\u002Fdiv>\n  \u003C\u002FTransition>\n\u003C\u002Ftemplate>\n\n\u003Cstyle>\n\u002F* CSS classes for name=\"fade\" *\u002F\n.fade-enter-active, .fade-leave-active { transition: opacity 0.5s; }\n.fade-enter-from, .fade-leave-to { opacity: 0; }\n\n\u002F* TransitionGroup *\u002F\n.list-enter-active, .list-leave-active { transition: all 0.5s; }\n.list-enter-from { opacity: 0; transform: translateX(30px); }\n.list-leave-to { opacity: 0; transform: translateX(-30px); }\n.list-move { transition: transform 0.5s; } \u002F* for reordering *\u002F\n\u003C\u002Fstyle>\n\n\u003Cscript setup>\nimport gsap from 'gsap'\nconst show = ref(true)\nconst items = ref([{ id: 1 }, { id: 2 }])\n\nfunction beforeEnter(el) { el.style.opacity = 0 }\nfunction enter(el, done) {\n  gsap.to(el, { opacity: 1, duration: 1, onComplete: done })\n}\nfunction leave(el, done) {\n  gsap.to(el, { opacity: 0, duration: 0.5, onComplete: done })\n}\n\u003C\u002Fscript>\n```\n\n## Execution Flow\n1. **Enter:** `before-enter` → `enter` (triggers CSS class `-enter-from`, then `-enter-active`, then `-enter-to`) → `after-enter`.\n2. **Leave:** `before-leave` → `leave` → `after-leave`.\n3. For `TransitionGroup`, `move` class applied when items reorder (using FLIP technique).\n\n## Practical Usage\n- Modal fade-in\u002Ffade-out.\n- List item add\u002Fremove animations.\n- Page transitions (with Vue Router).\n- Drag-and-drop reorder animations.\n\n## Interview Insight\nExplain that `TransitionGroup` uses **FLIP** (First, Last, Invert, Play) to animate position changes without reordering DOM elements. It applies `-move` class to calculate transforms.\n\n## Common Mistakes\n- Forgetting `appear` attribute for initial render animation.\n- Not setting `tag` on `TransitionGroup` (defaults to `span`, may break layout).\n- Using CSS transition and JS animation simultaneously without coordination.\n- Not providing `key` in `TransitionGroup` – required for tracking.\n\n## Best Practices\n- Use CSS for simple transitions, JavaScript libraries (GSAP) for complex animations.\n- Set `mode=\"out-in\"` for sequential enter\u002Fleave (e.g., modal replacement).\n- Use `duration` prop to specify transition times (object for enter\u002Fleave).\n\n## Performance Considerations\n- CSS transforms (`translate`, `scale`) are GPU accelerated, prefer over `width\u002Fheight`.\n- Too many simultaneous leave\u002Fenter animations can cause jank; limit concurrent transitions.\n- `TransitionGroup` reorders with `transform` – very performant.\n\n## Production Recommendations\n- Use `appear` for initial load animations.\n- For router views, wrap `\u003CRouterView>` in `\u003CTransition>` for page transitions.\n- Provide reduced motion media query for accessibility: `@media (prefers-reduced-motion)`.\n\n## Latest Vue Patterns\n- **`\u003CTransition>` with `enter-active-class`** – use custom CSS library (e.g., Animate.css).\n- **`\u003CTransition>` with `persisted` prop** – keep component alive during animation.\n- **`v-move`** class for fine-grained move animation.\n\n## Interview Tip\nShow how to animate a list when items are added\u002Fremoved: `TransitionGroup` with `move` class is key. Also mention that `Transition` does not work with `v-if` and `v-show` simultaneously – use one.\n\n## Common Follow-up\n*\"How do you animate route changes?\"* – Wrap `\u003CRouterView>` in `\u003CTransition>` and provide unique `:key=\"$route.fullPath\"` to trigger animation on route change.\n\n## Real-world Example\nTodo list with add\u002Fremove animations:\n```vue\n\u003Ctemplate>\n  \u003CTransitionGroup name=\"todo\" tag=\"ul\">\n    \u003Cli v-for=\"todo in todos\" :key=\"todo.id\">\n      {{ todo.text }}\n      \u003Cbutton @click=\"removeTodo(todo.id)\">X\u003C\u002Fbutton>\n    \u003C\u002Fli>\n  \u003C\u002FTransitionGroup>\n\u003C\u002Ftemplate>\n\n\u003Cstyle>\n.todo-enter-active, .todo-leave-active { transition: all 0.3s; }\n.todo-enter-from { opacity: 0; transform: translateY(20px); }\n.todo-leave-to { opacity: 0; transform: translateX(-20px); }\n.todo-move { transition: transform 0.3s; }\n\u003C\u002Fstyle>\n```\n\n## Advanced Notes\n`Transition` exposes `onBeforeEnter`, `onEnter`, `onAfterEnter`, `onBeforeLeave`, etc., as props. You can also use `css: false` to skip CSS class injection and fully control with JS. `TransitionGroup` uses a Map to track children; when a child is removed, it leaves in place while others move using FLIP.",[275,276,277,278,279],"transition","animation","transition-group","css-animation","gsap",{"id":136,"category":104,"question":281,"answer":282,"level":179,"tags":283},"How to build complex form architectures with validation, nested fields, and dynamic inputs in Vue?","## Core Concept\nComplex forms involve **nested reactive state** (objects\u002Farrays), **validation** (sync\u002Fasync, cross-field), **dynamic fields** (add\u002Fremove), and **performance optimisation** (lazy validation, debouncing). Use composables to encapsulate logic.\n\n## Syntax\n```vue\n\u003Cscript setup lang=\"ts\">\nimport { reactive, computed, watch } from 'vue'\n\ninterface FormData {\n  name: string\n  email: string\n  addresses: Array\u003C{ street: string; city: string }>\n}\n\nconst form = reactive\u003CFormData>({\n  name: '',\n  email: '',\n  addresses: [{ street: '', city: '' }]\n})\n\n\u002F\u002F Validation with computed\nconst errors = computed(() => ({\n  name: !form.name ? 'Name required' : null,\n  email: !\u002F\\S+@\\S+\\.\\S+\u002F.test(form.email) ? 'Invalid email' : null,\n  addresses: form.addresses.map(addr => ({\n    street: !addr.street ? 'Street required' : null,\n    city: !addr.city ? 'City required' : null\n  }))\n}))\n\nconst isValid = computed(() => \n  !errors.value.name && !errors.value.email && \n  errors.value.addresses.every(a => !a.street && !a.city)\n)\n\n\u002F\u002F Dynamic fields\nfunction addAddress() {\n  form.addresses.push({ street: '', city: '' })\n}\nfunction removeAddress(index: number) {\n  form.addresses.splice(index, 1)\n}\n\n\u002F\u002F Async validation (e.g., email unique)\nconst emailUnique = ref\u003Cboolean | null>(null)\nwatch(() => form.email, debounce(async (email) => {\n  if (!email) return\n  const res = await fetch(`\u002Fapi\u002Fcheck-email?email=${email}`)\n  emailUnique.value = await res.json()\n}, 500))\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"submit\">\n    \u003Cinput v-model=\"form.name\" \u002F>\n    \u003Cspan v-if=\"errors.name\">{{ errors.name }}\u003C\u002Fspan>\n\n    \u003Cinput v-model=\"form.email\" \u002F>\n    \u003Cspan v-if=\"errors.email\">{{ errors.email }}\u003C\u002Fspan>\n    \u003Cspan v-if=\"emailUnique === false\">Email already taken\u003C\u002Fspan>\n\n    \u003Cdiv v-for=\"(addr, idx) in form.addresses\" :key=\"idx\">\n      \u003Cinput v-model=\"addr.street\" placeholder=\"Street\" \u002F>\n      \u003Cspan v-if=\"errors.addresses[idx]?.street\">{{ errors.addresses[idx].street }}\u003C\u002Fspan>\n      \u003Cbutton @click=\"removeAddress(idx)\">Remove\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n    \u003Cbutton type=\"button\" @click=\"addAddress\">Add Address\u003C\u002Fbutton>\n\n    \u003Cbutton :disabled=\"!isValid\">Submit\u003C\u002Fbutton>\n  \u003C\u002Fform>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. Reactive form state tracks user input.\n2. Validation computed runs reactively, caching errors.\n3. Async validation triggers debounced API call.\n4. Dynamic fields modify the array, triggering re-render and re-validation.\n5. On submit, final validation and API call.\n\n## Practical Usage\n- Multi-step wizards.\n- Inline editable grids.\n- Form builders with JSON schema.\n- Large enterprise forms (100+ fields).\n\n## Interview Insight\nExplain that reactive arrays for dynamic fields are efficient because Vue tracks array mutations. For performance, use `shallowRef` for large forms and validate on blur, not on every keystroke.\n\n## Common Mistakes\n- Deeply nested reactive without `shallowRef` causing performance issues.\n- Not providing unique `key` for dynamic fields (causes input focus issues).\n- Validating on every input without debounce – costly.\n- Not resetting validation state after form submission.\n\n## Best Practices\n- Extract form logic into `useForm` composable.\n- Use a validation library (VeeValidate, Zod, Yup).\n- Debounce async validation.\n- Validate on submit and on field blur (not on input).\n- Use `v-model` with lazy modifier for async validation.\n\n## Performance Considerations\n- Large forms: use `shallowRef` for nested arrays.\n- Validate with computed (cached) instead of method.\n- Use `v-once` for static form labels.\n\n## Production Recommendations\n- Integrate with `Pinia` for form state persistence across steps.\n- Use `vee-validate` + `zod` for schema validation.\n- Implement unsaved changes guard with `onBeforeRouteLeave`.\n\n## Latest Vue Patterns\n- **`defineModel`** simplifies two-way binding on form components.\n- **`useTemplateRef`** for typed form refs (Vue 3.5+).\n- **`useForm`** composable pattern.\n\n## Interview Tip\nShow how to build a generic `useForm` that accepts schema and handles validation, submission, and reset.\n\n## Common Follow-up\n*\"How do you handle form validation for deeply nested objects?\"* – Use recursive computed or a library like `zod` to define schema and validate recursively.\n\n## Real-world Example\nCustom `useForm` composable:\n```ts\nfunction useForm\u003CT extends Record\u003Cstring, any>>(initial: T, rules: Record\u003Ckeyof T, (val: any) => string | null>) {\n  const data = reactive({ ...initial })\n  const errors = computed(() => {\n    const errs: Partial\u003CRecord\u003Ckeyof T, string>> = {}\n    for (const key in rules) {\n      const error = rules[key](data[key])\n      if (error) errs[key] = error\n    }\n    return errs\n  })\n  const isValid = computed(() => Object.keys(errors.value).length === 0)\n  async function submit(onSubmit: (data: T) => Promise\u003Cvoid>) {\n    if (!isValid.value) return\n    await onSubmit({ ...data })\n    Object.assign(data, initial) \u002F\u002F reset\n  }\n  return { data, errors, isValid, submit }\n}\n```\n\n## Advanced Notes\nFor very large forms (>100 fields), consider using `shallowReactive` and manual change tracking. Use `requestIdleCallback` for non-critical validation. In SSR, forms are client-only – use `\u003CClientOnly>` for components with `v-model` to avoid hydration mismatch.",[108,284,285,201],"validation","dynamic-fields",{"id":146,"category":287,"question":288,"answer":289,"level":179,"tags":290},"Error Handling","How to handle errors globally and locally in Vue: error boundaries, onErrorCaptured, and global error handlers?","## Core Concept\nVue provides multiple error handling levels:\n- **`onErrorCaptured`** – hook in a component to capture errors from descendants (like an error boundary).\n- **`app.config.errorHandler`** – global handler for all uncaught errors.\n- **`onUnhandledRejection`** – global promise rejection handler.\n- **`errorCaptured`** (Options API).\n\n## Syntax\n```vue\n\u003C!-- ErrorBoundary.vue -->\n\u003Cscript setup>\nimport { onErrorCaptured, ref } from 'vue'\n\nconst error = ref(null)\n\nonErrorCaptured((err, instance, info) => {\n  error.value = err\n  console.error(`Error in ${info}:`, err)\n  \u002F\u002F Return false to stop propagation\n  return false\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv v-if=\"error\">\n    \u003Ch2>Something went wrong\u003C\u002Fh2>\n    \u003Cp>{{ error.message }}\u003C\u002Fp>\n    \u003Cbutton @click=\"error = null\">Try again\u003C\u002Fbutton>\n  \u003C\u002Fdiv>\n  \u003Cslot v-else \u002F>\n\u003C\u002Ftemplate>\n```\n\n```js\n\u002F\u002F main.js\nimport { createApp } from 'vue'\nimport App from '.\u002FApp.vue'\n\nconst app = createApp(App)\n\napp.config.errorHandler = (err, instance, info) => {\n  console.error('Global error:', err)\n  \u002F\u002F Send to error tracking service (Sentry, LogRocket)\n  logErrorToService(err, info)\n}\n\napp.config.warnHandler = (msg, instance, trace) => {\n  console.warn(`Vue warn: ${msg}`, trace)\n}\n\nwindow.onunhandledrejection = (event) => {\n  console.error('Unhandled promise rejection:', event.reason)\n  app.config.errorHandler(event.reason, null, 'unhandled rejection')\n}\n\napp.mount('#app')\n```\n\n## Execution Flow\n1. Error occurs in a component (render, lifecycle, watcher, event handler).\n2. Vue propagates error up the component tree, calling `onErrorCaptured` hooks.\n3. If a hook returns `false`, stops propagation.\n4. If no boundary captures, error reaches `app.config.errorHandler`.\n5. If no global handler, Vue logs to console.\n\n## Reactivity Explanation\nError handlers are not reactive – they are called imperatively when errors happen.\n\n## Practical Usage\n- **Error boundaries** – UI fallback for component subtree.\n- **Global error logging** – send to Sentry, Bugsnag.\n- **Recovery UI** – retry button after async error.\n- **User feedback** – toast notifications for API errors.\n\n## Interview Insight\nExplain that `onErrorCaptured` can only capture errors from **descendant components**, not from the component itself. For async errors (e.g., `fetch`), you need try\u002Fcatch inside the component or composable.\n\n## Common Mistakes\n- Relying on `onErrorCaptured` for async operations inside the same component – won't work.\n- Not stopping propagation (`return false`) when you want to prevent parent handlers.\n- Forgetting to handle promise rejections globally.\n\n## Best Practices\n- Use error boundaries for major UI sections (dashboard, user profile).\n- Always use try\u002Fcatch in async actions and re-throw or handle.\n- Combine global error handler with logging service.\n- Provide a fallback UI and retry mechanism.\n\n## Performance Considerations\nError handlers have minimal overhead – they are only invoked on errors.\n\n## Production Recommendations\n- Integrate with `Sentry` or `LogRocket` for production error tracking.\n- Use `app.config.errorHandler` to mask errors in production (avoid exposing stack traces).\n- For SSR, error handlers run on both server and client – be careful with side effects.\n\n## Latest Vue Patterns\n- **`\u003CSuspense>`** has its own error handling via `onErrorCaptured` on the Suspense component.\n- **`onWatcherCleanup`** (Vue 3.5) can handle async watcher errors.\n\n## Interview Tip\nContrast `errorCaptured` in Vue 2 vs `onErrorCaptured` in Vue 3 – both work similarly, but Composition API version is more flexible. Also mention that error boundaries do not catch errors in event handlers – those need try\u002Fcatch.\n\n## Common Follow-up\n*\"How do you recover from an error in an error boundary?\"* – You can reset local state and re-render by changing a `key` on the boundary or remounting the component.\n\n## Real-world Example\nNested error boundaries:\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003CErrorBoundary>\n      \u003CUserProfile :userId=\"id\" \u002F>\n    \u003C\u002FErrorBoundary>\n    \u003CErrorBoundary>\n      \u003CUserStats :userId=\"id\" \u002F>\n    \u003C\u002FErrorBoundary>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport ErrorBoundary from '.\u002FErrorBoundary.vue'\nimport UserProfile from '.\u002FUserProfile.vue'\nimport UserStats from '.\u002FUserStats.vue'\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\n`onErrorCaptured` receives three arguments: `error`, `instance` (the component instance where error occurred), and `info` (a string like `'render'`, `'setup'`, `'watcher'`, `'native event handler'`). You can also call `error` propagation programmatically. For async errors in `setup`, wrap in try\u002Fcatch and re-throw to trigger boundary.",[153,291,292,293],"error-boundary","onErrorCaptured","global-handler",{"id":156,"category":295,"question":296,"answer":297,"level":179,"tags":298},"SSR","What are the basics of Server-Side Rendering (SSR) and hydration in Vue?","## Core Concept\n**SSR** renders Vue components on the server into HTML strings and sends fully rendered HTML to the client. **Hydration** attaches event listeners and makes the static HTML interactive on the client by reusing the existing DOM nodes.\n\n**Benefits:** Better SEO, faster perceived load, performance on slow devices. **Trade-offs:** Higher server load, complexity (need Node.js environment).\n\n## Syntax (using Vite SSR)\n```js\n\u002F\u002F server.js (Node.js)\nimport express from 'express'\nimport { createSSRApp } from 'vue'\nimport { renderToString } from 'vue\u002Fserver-renderer'\nimport App from '.\u002FApp.vue'\n\nconst app = express()\n\napp.get('*', async (req, res) => {\n  const vueApp = createSSRApp(App, { url: req.url })\n  const html = await renderToString(vueApp)\n  res.send(`\n    \u003C!DOCTYPE html>\n    \u003Chtml>\n      \u003Chead>\u003Ctitle>SSR Vue\u003C\u002Ftitle>\u003C\u002Fhead>\n      \u003Cbody>\n        \u003Cdiv id=\"app\">${html}\u003C\u002Fdiv>\n        \u003Cscript type=\"importmap\">...\u003C\u002Fscript>\n        \u003Cscript type=\"module\" src=\"\u002Fclient.js\">\u003C\u002Fscript>\n      \u003C\u002Fbody>\n    \u003C\u002Fhtml>\n  `)\n})\n\napp.listen(3000)\n```\n\n```js\n\u002F\u002F client.js (hydration)\nimport { createSSRApp } from 'vue'\nimport App from '.\u002FApp.vue'\n\nconst app = createSSRApp(App)\n\u002F\u002F Hydrate instead of mount\napp.mount('#app', true) \u002F\u002F second arg true for hydration\n```\n\n## Execution Flow\n1. Server receives request.\n2. Creates Vue app instance (per request).\n3. Resolves async data (e.g., `onServerPrefetch`).\n4. Renders app to HTML string using `renderToString`.\n5. Injects HTML into template and sends response.\n6. Browser loads HTML (visible immediately).\n7. Browser downloads client JS bundle.\n8. Client creates app and hydrates – attaches event listeners, makes interactive.\n\n## Reactivity Explanation\nOn server, reactivity is not needed after render. The server uses `createSSRApp` which disables some optimisations for SSR. Hydration reuses server-generated DOM; client reactivity takes over.\n\n## Practical Usage\n- Content-heavy sites (blogs, e-commerce, documentation).\n- SEO-critical pages.\n- Apps needing fast first contentful paint.\n\n## Interview Insight\nExplain that hydration means Vue expects the client DOM to match the server-rendered HTML exactly. Mismatches cause hydration errors and potential re-renders. Common causes: using `v-if` with different initial values on client vs server, browser-only globals (`window`, `localStorage`).\n\n## Common Mistakes\n- Using `window` or `document` in `setup()` – undefined on server.\n- Asynchronous data fetched only on client – causes mismatch.\n- Forgetting to use `createSSRApp` instead of `createApp` on server.\n- Not handling `onServerPrefetch` for async data.\n\n## Best Practices\n- Use `onServerPrefetch` for server-side data fetching.\n- Wrap browser-only code in `onMounted` (client-only).\n- Use `import.meta.env.SSR` to detect environment.\n- Use `@vueuse\u002Fhead` for managing meta tags.\n\n## Performance Considerations\n- SSR increases server load (CPU for rendering).\n- Hydration can be slow on large pages – use `lazy hydration` techniques.\n- Stream rendering (`renderToNodeStream`) improves TTFB.\n\n## Production Recommendations\n- Use Nuxt.js or Vite SSR plugin for production-ready setup.\n- Implement caching (HTTP cache, component cache).\n- Use `v-once` for static parts to reduce hydration cost.\n- Configure `ssr: { noExternal: [...] }` for proper dependency bundling.\n\n## Latest Vue Patterns\n- **`onServerPrefetch`** – async data fetching during SSR.\n- **`\u003CSuspense>`** with SSR – experimental but works.\n- **`v-memo`** can help reduce hydration work.\n\n## Interview Tip\nExplain the concept of **hydration mismatch**: if server renders one thing and client expects another, Vue will discard server DOM and re-render, losing performance benefits. Use `v-if` with same initial state, or use `ClientOnly` component.\n\n## Common Follow-up\n*\"How do you handle async data in SSR?\"* – Use `onServerPrefetch` which runs on server and stores data in the store (e.g., Pinia). Then on client, hydration picks up the initial state.\n\n## Real-world Example\nData fetching with `onServerPrefetch`:\n```vue\n\u003Cscript setup>\nimport { ref, onServerPrefetch, onMounted } from 'vue'\nconst data = ref(null)\n\nonServerPrefetch(async () => {\n  \u002F\u002F runs on server only\n  data.value = await fetchDataFromAPI()\n})\n\nonMounted(() => {\n  \u002F\u002F if data still null, fetch on client\n  if (!data.value) data.value = await fetchDataFromAPI()\n})\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\nStreaming SSR (renderToNodeStream) sends HTML in chunks, improving perceived performance. For large apps, consider **islands architecture** – partial hydration (e.g., Astro, Vue’s `client:visible` directive). Vue’s official `@vue\u002Fserver-renderer` supports `renderToStream`. Hydration can be delayed for non-critical components using `defer` attribute or custom lazy hydration strategies.",[299,300,301,302],"ssr","hydration","server-side-rendering","seo",{"id":166,"category":304,"question":305,"answer":306,"level":179,"tags":307},"Hydration","Explain hydration mismatches, how to debug them, and strategies for lazy\u002Fpartial hydration.","## Core Concept\n**Hydration mismatch** occurs when the client-side virtual DOM differs from the server-rendered DOM. Vue will then discard the server DOM and re-render client-side, causing performance loss and flickering.\n\n**Common causes:**\n- Browser-only globals (`window`, `localStorage`) leading to different initial state.\n- Different timestamps or random values on client vs server.\n- Asynchronous data loaded only on client.\n- Using `v-if` with conditions that differ.\n\n## Debugging Mismatches\n```js\n\u002F\u002F Enable verbose hydration warnings\napp.config.compilerOptions = {\n  comments: true\n}\n\u002F\u002F Or use Vue Devtools – shows hydration errors\n\n\u002F\u002F Custom hydration handler\napp.config.globalProperties.$hydration = (msg) => {\n  console.error('Hydration mismatch:', msg)\n}\n```\n\n## Strategies to Fix\n```vue\n\u003C!-- Strategy 1: use client-only wrapper -->\n\u003Cscript setup>\nimport { onMounted, ref } from 'vue'\nconst clientSide = ref(false)\nonMounted(() => clientSide.value = true)\n\u003C\u002Fscript>\n\u003Ctemplate>\n  \u003Cdiv v-if=\"clientSide\">\n    {{ window.innerWidth }} \u003C!-- only client -->\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003C!-- Strategy 2: suppress hydration with data-hydration-ignore -->\n\u003Cdiv data-hydration-ignore>{{ randomNumber }}\u003C\u002Fdiv>\n\n\u003C!-- Strategy 3: use same initial value on both sides -->\n\u003Cscript setup>\nconst timestamp = ref(Date.now()) \u002F\u002F will mismatch\n\u002F\u002F better:\nconst timestamp = ref(null)\nonMounted(() => timestamp.value = Date.now())\n\u003C\u002Fscript>\n\n\u003C!-- Strategy 4: lazy hydration with custom directive -->\n\u003Cdiv v-lazy-hydrate>\n  \u003CHeavyComponent \u002F>\n\u003C\u002Fdiv>\n```\n\n## Lazy\u002FPartial Hydration\n```vue\n\u003C!-- Lazy hydration component using IntersectionObserver -->\n\u003Cscript setup>\nimport { ref, onMounted, defineAsyncComponent } from 'vue'\nconst shouldHydrate = ref(false)\nlet observer: IntersectionObserver\n\nonMounted(() => {\n  observer = new IntersectionObserver(([entry]) => {\n    if (entry.isIntersecting) {\n      shouldHydrate.value = true\n      observer.disconnect()\n    }\n  })\n  observer.observe(document.getElementById('lazy-region'))\n})\n\u003C\u002Fscript>\n\u003Ctemplate>\n  \u003Cdiv id=\"lazy-region\">\n    \u003CHeavyComponent v-if=\"shouldHydrate\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Execution Flow\n1. Server renders HTML, includes placeholder or static content.\n2. Client downloads HTML and displays it.\n3. Client JS loads; Vue attempts hydration.\n4. If mismatch, Vue logs error and replaces the subtree with client render.\n5. For lazy hydration, we delay mounting certain components until needed.\n\n## Interview Insight\nExplain that `data-hydration-ignore` is not a built-in Vue feature but a common pattern. Nuxt has `client-only` component. The best practice is to ensure the same initial state by using `onMounted` for client-specific logic.\n\n## Common Mistakes\n- Ignoring hydration warnings in development (they indicate real issues).\n- Using `v-if` with server-only condition.\n- Not providing fallback content for client-only parts (causes layout shift).\n\n## Best Practices\n- Use `onMounted` for all browser API access.\n- Provide same initial data via props or store initial state.\n- Use `ClientOnly` component wrapper (create your own).\n- Enable SSR compatibility checks in linters.\n\n## Performance Considerations\n- Hydration can be expensive; lazy hydration improves Time To Interactive.\n- Partial hydration allows shipping less JS initially.\n\n## Production Recommendations\n- For large apps, consider using `nuxt` with `ssr: false` for some routes.\n- Use `vue-lazy-hydration` package.\n- Monitor hydration errors with error tracking.\n\n## Latest Vue Patterns\n- **`v-cloak`** – not for hydration but for preventing unstyled content.\n- **`\u003CSuspense>`** with SSR can delay hydration of async components.\n- **`defer`** attribute in custom components (Vue 3.5+ experimental).\n\n## Interview Tip\nExplain the difference between hydration and client-side rendering: hydration reuses existing DOM, CSR creates fresh DOM. SSR + hydration = best of both worlds but with constraints.\n\n## Common Follow-up\n*\"Can you have hydration without full Vue runtime?\"* – Yes, with techniques like `vue-petite` or islands architecture, but limited.\n\n## Real-world Example\n`ClientOnly` component to wrap browser-only content:\n```vue\n\u003C!-- ClientOnly.vue -->\n\u003Cscript setup>\nimport { ref, onMounted } from 'vue'\nconst mounted = ref(false)\nonMounted(() => mounted.value = true)\n\u003C\u002Fscript>\n\u003Ctemplate>\n  \u003Ctemplate v-if=\"mounted\">\n    \u003Cslot \u002F>\n  \u003C\u002Ftemplate>\n  \u003Ctemplate v-else>\n    \u003Cslot name=\"fallback\" \u002F>\n  \u003C\u002Ftemplate>\n\u003C\u002Ftemplate>\n\n\u003C!-- Usage -->\n\u003CClientOnly>\n  \u003CChart :data=\"data\" \u002F>\n  \u003Ctemplate #fallback>\n    \u003Cdiv class=\"chart-placeholder\">Loading chart...\u003C\u002Fdiv>\n  \u003C\u002Ftemplate>\n\u003C\u002FClientOnly>\n```\n\n## Advanced Notes\nHydration can be performed in chunks using `hydrate` function from `vue\u002Fserver-renderer` with `vnode` and `container`. For incremental hydration, libraries like `is-land` (11ty) or `@vue\u002Flazy-hydration` exist. Vue 3 core team is exploring **resumability** (like Qwik) but not yet stable.",[300,299,308,309],"mismatch","lazy-hydration",{"id":311,"category":312,"question":313,"answer":314,"level":179,"tags":315},20,"Composables","What are VueUse patterns and how to leverage its utilities for common tasks?","## Core Concept\nVueUse is a collection of Composition API utilities for common patterns: reactive state, DOM events, browser APIs, and more. It follows best practices (cleanup, SSR safety, TypeScript) and is tree-shakeable.\n\n## Common VueUse Utilities\n```vue\n\u003Cscript setup>\nimport { ref } from 'vue'\nimport {\n  useLocalStorage,\n  useMouse,\n  useDebounceFn,\n  useThrottleFn,\n  useIntervalFn,\n  useEventListener,\n  useTitle,\n  useDark,\n  useToggle,\n  useFetch,\n  useClipboard\n} from '@vueuse\u002Fcore'\n\n\u002F\u002F Persistent state\nconst settings = useLocalStorage('app-settings', { theme: 'dark', notifications: true })\n\n\u002F\u002F Mouse tracking (reactive)\nconst { x, y } = useMouse()\n\n\u002F\u002F Debounced function\nconst debouncedSearch = useDebounceFn((query) => {\n  console.log('Searching for', query)\n}, 300)\n\n\u002F\u002F Throttled scroll handler\nconst onScroll = useThrottleFn(() => {\n  console.log(window.scrollY)\n}, 100)\n\n\u002F\u002F Interval\nconst { pause, resume, isActive } = useIntervalFn(() => {\n  console.log('tick')\n}, 1000)\n\n\u002F\u002F Title management\nconst title = useTitle('My App')\n\n\u002F\u002F Dark mode\nconst isDark = useDark()\nconst toggleDark = useToggle(isDark)\n\n\u002F\u002F Fetch data\nconst { data, isFetching, error, execute } = useFetch('\u002Fapi\u002Fusers').get().json()\n\n\u002F\u002F Clipboard\nconst { copy, copied } = useClipboard()\n\n\u002F\u002F Event listener (auto cleanup)\nuseEventListener('resize', () => console.log('resized'))\n\u003C\u002Fscript>\n```\n\n## Execution Flow\nVueUse composables follow the same pattern: create reactive state, register lifecycle hooks for cleanup, return reactive refs. They handle SSR by checking `typeof window !== 'undefined'`.\n\n## Practical Usage\n- **State persistence** – `useLocalStorage`, `useSessionStorage`.\n- **DOM events** – `useEventListener`, `useMouse`, `useScroll`, `useResizeObserver`.\n- **Async utilities** – `useDebounceFn`, `useThrottleFn`, `useIntervalFn`, `useTimeoutFn`.\n- **Browser APIs** – `useClipboard`, `useShare`, `useWebSocket`.\n- **Sensors** – `useIdle`, `useOnline`, `usePageLeave`.\n\n## Interview Insight\nExplain that VueUse is not official Vue but is widely adopted and maintained by Vue core team members. It demonstrates advanced composable patterns and is safe for production.\n\n## Common Mistakes\n- Using VueUse utilities without understanding cleanup (they handle it, but be aware).\n- Not importing from the correct subpath for tree-shaking (use direct imports).\n- Assuming all utilities work in SSR (many do, some are client-only – check docs).\n\n## Best Practices\n- Install `@vueuse\u002Fcore` and import only what you need.\n- Use `@vueuse\u002Fnuxt` for Nuxt integration.\n- Combine multiple VueUse utilities in custom composables.\n- Use `useLocalStorage` instead of manual localStorage to ensure reactivity.\n\n## Performance Considerations\nVueUse utilities are lightweight and lazy (they don't create effects until called). Some use `requestAnimationFrame` or `resizeObserver` – be mindful of many instances.\n\n## Production Recommendations\n- For SSR, use `useLocalStorage` with `shallowRef` to avoid hydration issues.\n- Use `useDebounceFn` on search inputs to reduce API calls.\n- Use `useEventListener` for manual DOM refs: `useEventListener(elRef, 'click', handler)`.\n\n## Latest Vue Patterns\n- **`useTemplateRef`** – Vue 3.5, but VueUse has `useTemplateRefsList`.\n- **`useFetch`** now supports `beforeFetch`, `afterFetch`, `onFetchError`.\n- **`useWebWorker`** for offloading heavy computations.\n\n## Interview Tip\nShow how to build a custom composable using VueUse as building blocks: `useUserLocation` combining `useGeolocation` and `useLocalStorage`.\n\n## Common Follow-up\n*\"Is VueUse necessary if I have Pinia?\"* – They serve different purposes. Pinia is for global state; VueUse is for utilities and reactive browser APIs. Often used together.\n\n## Real-world Example\nSearch component with debounced input and persistent history:\n```vue\n\u003Cscript setup>\nimport { ref } from 'vue'\nimport { useDebounceFn, useLocalStorage, useFetch } from '@vueuse\u002Fcore'\n\nconst query = ref('')\nconst history = useLocalStorage('search-history', [])\n\nconst { data, isFetching } = useFetch(() => `\u002Fapi\u002Fsearch?q=${query.value}`).get().json()\n\nconst debouncedSearch = useDebounceFn(() => {\n  if (query.value) {\n    history.value.unshift(query.value)\n    history.value = [...new Set(history.value)].slice(0, 10)\n  }\n}, 500)\n\nwatch(query, () => debouncedSearch())\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cinput v-model=\"query\" placeholder=\"Search...\" \u002F>\n  \u003Cdiv v-if=\"isFetching\">Loading...\u003C\u002Fdiv>\n  \u003Cdiv v-else>{{ data }}\u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nVueUse also offers `createSharedComposable` to share state across multiple components, `createGlobalState` for singleton, and `createReusableTemplate` for template patterns. The library is modular – you can import `@vueuse\u002Fshared` and `@vueuse\u002Fcore` separately. The `@vueuse\u002Fcomponents` provides renderless components.",[316,201,317,318],"vueuse","utilities","browser-apis",[320,329,337,346,353,358,364,372,380,390,396,403,408,418,426],{"id":6,"category":321,"question":322,"answer":323,"level":324,"tags":325},"Vue Internals","Explain Vue 3's reactivity system internals: Proxy traps, track and trigger, effect scheduling, and dependency collection.","## Core Concept\nVue 3 reactivity is built on three core primitives: `Proxy` for interception, `track` for dependency collection, and `trigger` for effect re-execution. The system is fully decoupled from the component system and can be used standalone.\n\n**Key components:**\n- **`targetMap`** – WeakMap storing dependency maps per reactive object.\n- **`activeEffect`** – the currently running effect (e.g., component render, computed, watch).\n- **`effect`** – function that wraps a user callback and tracks dependencies.\n- **`track`** – adds current effect to the dependency map for a property.\n- **`trigger`** – finds all effects depending on a property and schedules them.\n\n## Syntax (simplified internal pseudocode)\n```js\nlet activeEffect = null\nconst targetMap = new WeakMap()\n\nfunction track(target, key) {\n  if (activeEffect) {\n    let depsMap = targetMap.get(target)\n    if (!depsMap) targetMap.set(target, (depsMap = new Map()))\n    let dep = depsMap.get(key)\n    if (!dep) depsMap.set(key, (dep = new Set()))\n    dep.add(activeEffect)\n  }\n}\n\nfunction trigger(target, key) {\n  const depsMap = targetMap.get(target)\n  if (!depsMap) return\n  const dep = depsMap.get(key)\n  if (dep) dep.forEach(effect => effect.scheduler ? effect.scheduler() : effect())\n}\n\nfunction reactive(obj) {\n  return new Proxy(obj, {\n    get(target, key) {\n      track(target, key)\n      return Reflect.get(target, key)\n    },\n    set(target, key, value) {\n      const result = Reflect.set(target, key, value)\n      trigger(target, key)\n      return result\n    }\n  })\n}\n\nfunction effect(fn, options = {}) {\n  const effectFn = () => {\n    try {\n      activeEffect = effectFn\n      return fn()\n    } finally {\n      activeEffect = null\n    }\n  }\n  effectFn.scheduler = options.scheduler\n  effectFn() \u002F\u002F run immediately\n  return effectFn\n}\n```\n\n## Execution Flow\n1. **Initialisation:** `reactive(obj)` creates a Proxy wrapping the original object.\n2. **Tracking:** When an effect runs (e.g., component render), it sets `activeEffect` to itself and reads a reactive property → Proxy `get` trap calls `track`, adding current effect to `targetMap`.\n3. **Triggering:** When a property is assigned → Proxy `set` trap calls `trigger`, which looks up all effects depending on that property and calls their scheduler (or the effect directly).\n4. **Scheduling:** For component updates, the scheduler queues the effect in a microtask queue (batching). For `watchSyncEffect`, it runs synchronously.\n\n## Reactivity Explanation\nThe system is **lazy** – effects only re-run when accessed dependencies change. It handles nested effects (effect inside effect) via a stack, and supports cleanup via `onCleanup`.\n\n## Practical Usage\n- Understanding this helps debug edge cases (e.g., why reactivity breaks after destructuring).\n- Creating custom reactive data structures (e.g., `shallowReactive`, `readonly`).\n- Optimising performance by reducing dependency tracking overhead.\n\n## Interview Insight\nExplain that Vue's reactivity is **not a dirty-checking** system (like AngularJS) nor a virtual DOM diff for state (like React). It's a fine-grained reactive system where each property tracks its own dependencies. This makes updates very efficient.\n\n## Common Mistakes\n- Mutating reactive objects outside of effects (no tracking, no trigger).\n- Reassigning a reactive variable (`let state = reactive({}); state = reactive({})`) loses reactivity because the proxy reference changes.\n- Forgetting that `Proxy` cannot intercept direct property access on primitives (hence `ref`).\n\n## Best Practices\n- Prefer `ref` for primitives; `reactive` for objects that won't be reassigned.\n- Use `toRaw` to temporarily escape reactivity for performance-heavy operations.\n- Use `markRaw` to prevent unnecessary proxy wrapping for large read-only data.\n\n## Performance Considerations\n- Proxy overhead is minimal for typical apps but can be noticeable for huge arrays (use `shallowRef`).\n- Deep reactivity traverses all nested objects at creation – use `shallowReactive` for large, flat structures.\n- Avoid creating many reactive objects in loops; batch updates.\n\n## Production Recommendations\n- Use `shallowRef` for large data arrays (e.g., tables with >10k rows).\n- Combine `triggerRef` to manually force updates after mutating `shallowRef` content.\n- Profile reactivity cost with Vue Devtools' \"Track Op\" feature.\n\n## Latest Vue Patterns\n- **`effectScope`** – groups effects for manual disposal (useful for component-like logic in non-component contexts).\n- **`customRef`** – create your own ref with controlled `track`\u002F`trigger` (e.g., debounced ref).\n- **`toValue`** – unwraps refs and calls getters, used internally in Vue 3.3+.\n\n## Interview Tip\nAsk: \"What happens if you access a reactive property inside a `setTimeout` callback?\" – It will still work because the callback reads the latest value, but the read is not tracked unless the callback is itself an effect. To make it reactive, wrap in `watch` or `effect`.\n\n## Common Follow-up\n*\"How does Vue handle nested reactive objects?\"* – When a reactive object is accessed and the value is another object, `get` trap calls `reactive` on that nested object recursively (lazy deep reactivity).\n\n## Real-world Example\nStandalone reactivity outside Vue components:\n```js\nimport { reactive, effect } from '@vue\u002Freactivity'\n\nconst state = reactive({ count: 0 })\nlet double\n\neffect(() => {\n  double = state.count * 2\n  console.log(`Double is ${double}`)\n})\n\nstate.count = 2 \u002F\u002F logs \"Double is 4\"\n```\n\n## Advanced Notes\nVue's reactivity is built on the `@vue\u002Freactivity` package. The scheduler distinguishes between `queuePreFlushCb`, `queuePostFlushCb`, and sync jobs. `watchEffect` uses `effect` with `scheduler` that queues the effect. The `targetMap` uses `WeakMap` so unreachable objects can be garbage-collected, preventing memory leaks.","advanced",[81,326,327,251,328],"proxy","track-trigger","effect",{"id":17,"category":321,"question":330,"answer":331,"level":324,"tags":332},"How does Vue's virtual DOM and diffing algorithm work? Explain patch flags, block tree, and the rendering pipeline.","## Core Concept\nVue's virtual DOM (VDOM) is a JavaScript representation of the real DOM. When state changes, Vue creates a new VDOM tree, diffs it against the old one, and applies minimal mutations to the real DOM. Vue 3 adds **compile-time optimisations**: patch flags, block tree, and static hoisting.\n\n**Key components:**\n- **`createVNode`** – creates VNode objects with type, props, children, and patch flags.\n- **`render`** – entry point that calls `patch` to mount or update.\n- **`patch`** – recursive diffing function.\n- **`patchFlag`** – bitmask indicating which parts of a VNode are dynamic.\n- **Block tree** – flattens dynamic nodes for fast iteration.\n\n## Execution Flow (Simplified)\n```js\n\u002F\u002F Compiler output for \u003Cdiv :class=\"cls\">{{ msg }}\u003C\u002Fdiv>\nimport { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from 'vue'\n\nfunction render(_ctx, _cache) {\n  return (_openBlock(), _createBlock(\"div\", {\n    class: _ctx.cls\n  }, _toDisplayString(_ctx.msg), 1 \u002F* TEXT *\u002F))\n}\n```\n\n**Patch flags:**\n- `1` = `TEXT` – dynamic text content\n- `2` = `CLASS` – dynamic class binding\n- `4` = `STYLE` – dynamic style\n- `8` = `PROPS` – dynamic non-class\u002Fstyle props\n- `16` = `FULL_PROPS` – dynamic props that include keys\n- `32` = `HYDRATE_EVENTS` – event listeners\n- `64` = `STABLE_FRAGMENT` – fragment with stable children\n- `128` = `KEYED_FRAGMENT` – fragment with keyed children\n- `256` = `UNKEYED_FRAGMENT` – fragment with unkeyed children\n- `512` = `NEED_PATCH` – component needs non-props\u002Fclass\u002Fstyle patch\n- `1024` = `DYNAMIC_SLOTS` – dynamic slots\n\n**Block tree:** dynamic children are collected in an array, so diffing skips static nodes.\n\n## Reactivity Explanation\nThe VDOM is not reactive itself – it's recreated on each render. The reactivity system triggers the component's render effect, which generates a new VDOM tree and then calls `patch`.\n\n## Practical Usage\n- Understanding this helps optimise large lists and dynamic components.\n- Using `v-memo` or `v-once` to reduce diffing work.\n- Debugging rendering performance with Vue Devtools.\n\n## Interview Insight\nExplain that Vue's compiler adds patch flags to VNodes, telling the runtime what to diff. This makes Vue's VDOM faster than React's, which requires manual `shouldComponentUpdate` or `React.memo`. The block tree further reduces diffing overhead by flattening dynamic nodes.\n\n## Common Mistakes\n- Assuming all VDOMs are the same – Vue's is optimised, React's is not.\n- Overusing dynamic components without `key` – forces full replacement.\n- Not providing `key` in `v-for` – disables block tree optimisation for that list.\n\n## Best Practices\n- Use `v-memo` for expensive list items with stable sub-trees.\n- Prefer static content where possible – compiler hoists it out of render.\n- Use `shallowRef` for large arrays to avoid deep VDOM generation overhead.\n\n## Performance Considerations\n- Patch flags allow skipping entire property diffing – huge win.\n- Block tree reduces O(n) iteration over static nodes.\n- `v-once` caches VNodes – zero diffing cost for that subtree.\n- Dynamic component switching without `key` forces full VDOM discard.\n\n## Production Recommendations\n- Use `v-memo` on long lists with infrequent changes.\n- Profile with `@vue\u002Fdevtools` timeline to see render durations.\n- For extremely dynamic content, consider using `jsx` or manual render functions for fine control.\n\n## Latest Vue Patterns\n- **`v-memo`** – explicitly tells Vue to skip diffing a subtree if dependencies haven't changed.\n- **`v-once`** – static content never updates.\n- **`defineAsyncComponent`** – code-splitting reduces initial VDOM size.\n\n## Interview Tip\nExplain the difference between `patchFlag` and `blockTree`: patch flags mark per-VNode dynamic properties, while block tree aggregates dynamic children for fast iteration during diff. Both are compile-time optimisations.\n\n## Common Follow-up\n*\"How does Vue's diff compare to React's?\"* – Vue's is more optimised at compile time, React's relies on runtime heuristics. Vue's diff algorithm is also more efficient for keyed lists using longest increasing subsequence, similar to React.\n\n## Real-world Example\nExamine compiled output of a template:\n```vue\n\u003Ctemplate>\n  \u003Cdiv class=\"static\" :class=\"dynamic\">{{ text }}\u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\u002F\u002F compiled:\n\u002F\u002F createVNode(\"div\", { class: _ctx.dynamic }, _toDisplayString(_ctx.text), 2 \u002F* CLASS *\u002F | 1 \u002F* TEXT *\u002F)\n```\n\n## Advanced Notes\nThe `patch` function uses `switch` on VNode `type` (element, component, text, comment, fragment). For elements, it uses `patchElement` which iterates over patch flags. The block tree is created by `openBlock()` and `createBlock()`, which collects dynamic children in an array. This allows the patcher to iterate only over those children, skipping static ones.",[333,72,334,335,336],"virtual-dom","patch-flags","block-tree","rendering",{"id":24,"category":321,"question":338,"answer":339,"level":324,"tags":340},"How does the Vue compiler work? Explain template compilation, AST transformation, and code generation.","## Core Concept\nVue's compiler transforms SFC templates into JavaScript render functions. The process has three stages: **parsing** (template → AST), **transformation** (AST → optimized AST), and **code generation** (AST → render function code).\n\n**Key components:**\n- **Parser** – uses HTML tokeniser to build an Abstract Syntax Tree (AST).\n- **Transformers** – apply optimisations: hoist static nodes, identify patch flags, create block tree.\n- **Codegen** – generates render function code with `createVNode` calls.\n\n## Execution Flow (Simplified)\n```js\n\u002F\u002F From: https:\u002F\u002Fvuejs.org\u002Fguide\u002Fscaling-up\u002Ftooling.html#note-on-in-browser-template-compilation\nimport { compile } from '@vue\u002Fcompiler-dom'\n\nconst template = `\u003Cdiv :class=\"cls\">{{ msg }}\u003C\u002Fdiv>`\nconst { code } = compile(template, { mode: 'module' })\nconsole.log(code)\n\u002F\u002F Output:\n\u002F\u002F import { toDisplayString as _toDisplayString, createVNode as _createVNode, ... } from 'vue'\n\u002F\u002F export function render(_ctx, _cache) {\n\u002F\u002F   return _createVNode(\"div\", { class: _ctx.cls }, _toDisplayString(_ctx.msg), 1 \u002F* TEXT *\u002F)\n\u002F\u002F }\n```\n\n**AST Example:**\n```js\n{\n  type: 1, \u002F\u002F NodeTypes.ELEMENT\n  tag: 'div',\n  props: [{ type: 6, name: 'class', value: { content: 'cls', isStatic: false } }],\n  children: [{ type: 2, content: 'msg', isStatic: false }]\n}\n```\n\n**Transformations:**\n- **Static hoisting** – moves static VNodes out of render function (they are created once).\n- **Patch flags** – adds `patchFlag` to VNode calls.\n- **Block tree** – wraps dynamic children in `openBlock`\u002F`createBlock`.\n- **Cache handlers** – inline handlers are cached to avoid re-renders.\n\n## Reactivity Explanation\nThe compiler outputs code that uses reactivity (e.g., `_ctx.msg`). The generated render function is wrapped in a reactive effect by the runtime.\n\n## Practical Usage\n- Understanding compilation helps debug performance issues.\n- Custom compiler macros (like `defineProps`, `defineModel`).\n- Building custom DSLs on top of Vue.\n\n## Interview Insight\nExplain that Vue supports two compilation modes: **build-time** (recommended) using `vue-loader` or `@vitejs\u002Fplugin-vue`, and **runtime** (using `compile` in the browser) which is slower and larger. Most production apps use build-time compilation.\n\n## Common Mistakes\n- Assuming runtime compilation is as fast – it's slower and increases bundle size.\n- Overusing `v-html` – bypasses compilation optimisations.\n- Not using `v-bind` in object mode for many dynamic props (reduces patch flags).\n\n## Best Practices\n- Always pre-compile templates (Vite\u002FWebpack).\n- Use `\u003Cscript setup>` – compiles to efficient render functions.\n- Avoid complex expressions in templates – they are re-evaluated on each render.\n- Use `v-once` for truly static parts.\n\n## Performance Considerations\n- Build-time compilation produces highly optimised JavaScript.\n- Static hoisting reduces memory and GC pressure.\n- Patch flags make runtime diffing faster by skipping unchanged categories.\n\n## Production Recommendations\n- Enable `hoistStatic` and `cacheHandlers` in compiler options (default in production).\n- Use `@vue\u002Fcompiler-sfc` for custom compilation pipelines.\n- For library authors, pre-compile components to JS to reduce consumer bundle size.\n\n## Latest Vue Patterns\n- **`defineModel` macro** – compiles to `modelValue` prop + `update:modelValue` emit.\n- **`defineOptions`** – sets component options like `name`, `inheritAttrs`.\n- **Generic components** – `defineProps\u003C{ item: T }>()` uses compiler for type extraction.\n\n## Interview Tip\nExplain that the compiler is **framework-agnostic** – you can use `@vue\u002Fcompiler-dom` to compile templates to render functions that work with any DOM-based runtime. The `@vue\u002Fcompiler-sfc` is the SFC compiler used by Vite\u002FWebpack.\n\n## Common Follow-up\n*\"What is the difference between compile-time and runtime transforms?\"* – Compile-time transforms run during build (e.g., converting `v-model` to props\u002Fevents). Runtime transforms happen in the browser (e.g., `compile` function).\n\n## Real-world Example\nCustom macro that transforms `$t('key')` to a translation function:\n```js\n\u002F\u002F vite-plugin-vue-macro.js\nexport function transform(code, id) {\n  if (id.endsWith('.vue')) {\n    return code.replace(\u002F\\$t\\(['\"]([^'\"]+)['\"]\\)\u002Fg, (_, key) => `i18n.global.t('${key}')`)\n  }\n}\n```\n\n## Advanced Notes\nThe AST uses an extensible `NodeTypes` enum. Transformers can be plugged in via `@vue\u002Fcompiler-core`'s `transform` function. Vue's compiler also supports **template refs** transformation, **v-memo** transformation, and **v-is** (for dynamic component). The output render function uses `_createVNode` and `_openBlock` which are aliases to runtime functions. Codegen also generates `withCtx` for slots and `renderList` for `v-for`.",[341,342,343,344,345],"compiler","ast","codegen","transformation","templates",{"id":32,"category":321,"question":347,"answer":348,"level":324,"tags":349},"What is the scheduler in Vue? Explain job queueing, nextTick, and flush options.","## Core Concept\nThe Vue scheduler batches reactive updates and DOM mutations for performance. When reactive state changes, effects are not executed immediately but queued in a **microtask queue**. The scheduler deduplicates multiple updates to the same effect and flushes them asynchronously.\n\n**Key components:**\n- **`queue`** – array of jobs (effects) to be flushed.\n- **`pending`** – boolean flag if a flush is already scheduled.\n- **`nextTick`** – adds a callback to run after the current flush.\n- **`flushPre`** \u002F **`flushPost`** – different queues for lifecycle hooks.\n\n## Execution Flow (Simplified)\n```js\nlet isFlushing = false\nlet isFlushPending = false\nconst queue = []\n\nfunction queueJob(job) {\n  if (!queue.includes(job)) {\n    queue.push(job)\n    queueFlush()\n  }\n}\n\nfunction queueFlush() {\n  if (!isFlushPending && !isFlushing) {\n    isFlushPending = true\n    Promise.resolve().then(flushJobs)\n  }\n}\n\nfunction flushJobs() {\n  isFlushPending = false\n  isFlushing = true\n  \u002F\u002F sort queue for consistency\n  queue.sort((a, b) => a.id - b.id)\n  for (let i = 0; i \u003C queue.length; i++) {\n    queue[i]()\n  }\n  queue.length = 0\n  isFlushing = false\n}\n```\n\n**Flush types:**\n- **`pre`** (default) – effects run before component updates (e.g., `watch`).\n- **`post`** – effects run after component updates (e.g., `watchPostEffect`).\n- **`sync`** – runs synchronously (no batching, e.g., `watchSyncEffect`).\n\n## Reactivity Explanation\nWhen a reactive setter triggers, it calls `trigger` which finds all dependent effects. Each effect's scheduler (e.g., `queuePreFlushCb`, `queuePostFlushCb`) pushes the effect into the appropriate queue.\n\n## Practical Usage\n- Using `nextTick` to wait for DOM updates.\n- Performance tuning: batch synchronous updates via `flush: 'sync'` (rare).\n- Debugging update order issues.\n\n## Interview Insight\nExplain that Vue's scheduler is **microtask-based** (uses `Promise.resolve().then`). This means the flush happens after all synchronous code completes but before any macrotasks (like `setTimeout`). This is similar to React's batching but Vue does it automatically.\n\n## Common Mistakes\n- Assuming DOM updates happen immediately after state change – they don't (unless `flush: 'sync'`).\n- Creating circular updates (e.g., updating state in `watchPostEffect` that triggers another update).\n- Overusing `nextTick` when `watchPostEffect` would suffice.\n\n## Best Practices\n- Use `watchPostEffect` for DOM-reading side effects.\n- Use `nextTick` only when you need to wait for a specific update.\n- Avoid synchronous effects (`flush: 'sync'`) except for very specific low-level use cases.\n\n## Performance Considerations\n- Batching prevents multiple DOM updates per mutation.\n- Sorting jobs by `id` ensures parent components update before children.\n- Infinite loops are prevented by the queue deduplication.\n\n## Production Recommendations\n- Let Vue handle scheduling; avoid manual `nextTick` unless necessary.\n- Use `onUnmounted` to cancel pending effects if needed.\n- In tests, use `await nextTick()` or `await flushPromises()` after state updates.\n\n## Latest Vue Patterns\n- **`watchPostEffect`** – built-in alias for `watchEffect` with `flush: 'post'`.\n- **`watchSyncEffect`** – alias for `flush: 'sync'`.\n- **`queuePostRenderEffect`** – internal, used by `\u003CTransition>`.\n\n## Interview Tip\nExplain the difference between `nextTick` and `setTimeout`: `nextTick` uses microtasks (higher priority), so it runs before any `setTimeout` callback in the same event loop. This ensures DOM updates are applied before user timers.\n\n## Common Follow-up\n*\"Can multiple `nextTick` callbacks be batched?\"* – Yes, if you call `nextTick` multiple times before the flush, all callbacks are queued and executed after the same flush.\n\n## Real-world Example\nScroll to bottom after adding message:\n```js\nasync function addMessage(msg) {\n  messages.value.push(msg)\n  await nextTick()\n  const container = messagesContainer.value\n  container.scrollTop = container.scrollHeight\n}\n```\n\n## Advanced Notes\nThe scheduler also has `queuePreFlushCb` and `queuePostFlushCb` for lifecycle hooks. `onMounted` and `onUpdated` are queued with `post` to run after DOM updates. The `job.id` ensures that if a component's update effect is triggered multiple times, it is queued only once. The flush function also handles recursive updates by checking `isFlushing` and preventing nested flushes.",[258,256,350,351,352],"queue","batching","microtask",{"id":41,"category":295,"question":354,"answer":355,"level":324,"tags":356},"Explain streaming SSR, Suspense SSR, and advanced hydration strategies (lazy, selective, partial).","## Core Concept\n**Streaming SSR** sends HTML in chunks as they are rendered, improving Time To First Byte (TTFB). **Suspense SSR** allows rendering async components on the server with fallback content, then streaming the resolved content later. **Advanced hydration** selectively hydrates parts of the page to improve Time To Interactive (TTI).\n\n## Streaming SSR Syntax\n```js\n\u002F\u002F Node.js server with streaming\nimport { createSSRApp } from 'vue'\nimport { renderToNodeStream } from '@vue\u002Fserver-renderer'\nimport express from 'express'\n\nconst app = express()\napp.get('\u002F', (req, res) => {\n  const vueApp = createSSRApp(App, { url: req.url })\n  const stream = renderToNodeStream(vueApp)\n  res.write(`\u003C!DOCTYPE html>\u003Chtml>\u003Chead>...\u003C\u002Fhead>\u003Cbody>\u003Cdiv id=\"app\">`)\n  stream.pipe(res, { end: false })\n  stream.on('end', () => {\n    res.write(`\u003C\u002Fdiv>\u003Cscript src=\"\u002Fclient.js\">\u003C\u002Fscript>\u003C\u002Fbody>\u003C\u002Fhtml>`)\n    res.end()\n  })\n})\n```\n\n## Suspense SSR\n```vue\n\u003C!-- Parent.vue -->\n\u003Ctemplate>\n  \u003CSuspense>\n    \u003Ctemplate #default>\n      \u003CAsyncDataComponent \u002F>\n    \u003C\u002Ftemplate>\n    \u003Ctemplate #fallback>\n      \u003CLoadingSpinner \u002F>\n    \u003C\u002Ftemplate>\n  \u003C\u002FSuspense>\n\u003C\u002Ftemplate>\n\n\u003C!-- AsyncDataComponent.vue -->\n\u003Cscript setup>\n\u002F\u002F Using top-level await\nconst data = await fetchData()\n\u003C\u002Fscript>\n```\nOn server, `\u003CSuspense>` will wait for the async dependency, then stream the resolved content. Multiple Suspense boundaries can be streamed independently.\n\n## Advanced Hydration\n```js\n\u002F\u002F Lazy hydration with IntersectionObserver\nimport { h, defineComponent, onMounted, ref } from 'vue'\n\nconst LazyHydrate = defineComponent({\n  props: ['when'],\n  setup(props, { slots }) {\n    const hydrated = ref(false)\n    const el = ref()\n    onMounted(() => {\n      if (props.when === 'visible') {\n        const observer = new IntersectionObserver(([entry]) => {\n          if (entry.isIntersecting) {\n            hydrated.value = true\n            observer.disconnect()\n          }\n        })\n        observer.observe(el.value)\n      } else if (props.when === 'idle') {\n        requestIdleCallback(() => { hydrated.value = true })\n      } else {\n        hydrated.value = true\n      }\n    })\n    return () => hydrated.value ? slots.default() : h('div', { ref: el }, slots.placeholder?.())\n  }\n})\n```\n\n## Execution Flow\n1. Server starts rendering → streams opening HTML tags.\n2. When hitting a `\u003CSuspense>` boundary, server renders fallback, streams it, continues.\n3. Async component resolves → server pushes replacement HTML via script tags.\n4. Client receives initial HTML, displays fallback, then replaces with resolved content.\n5. Client JS loads, hydrates only visible\u002Factive components (lazy).\n\n## Reactivity Explanation\nStreaming SSR does not change reactivity on client. Hydration still attaches event listeners to server-generated DOM.\n\n## Interview Insight\nExplain that `renderToNodeStream` is more efficient than `renderToString` for large pages because it starts sending data immediately, reducing perceived latency. However, it requires careful handling of async components and Suspense boundaries.\n\n## Common Mistakes\n- Using streaming with `renderToString` – defeats purpose.\n- Not handling stream errors – server may hang.\n- Assuming lazy hydration works with all components (e.g., components that need immediate interactivity).\n\n## Best Practices\n- Use streaming for content-heavy pages.\n- Combine with `onServerPrefetch` for data fetching.\n- Use selective hydration for below-the-fold content.\n- Provide meaningful placeholders for lazy-hydrated components.\n\n## Performance Considerations\n- Streaming reduces TTFB but may increase total HTML size (due to fallback content).\n- Lazy hydration reduces TTI but may cause layout shifts.\n- Each Suspense boundary adds overhead; use sparingly.\n\n## Production Recommendations\n- Use Nuxt.js which has built-in streaming and Suspense support.\n- For custom SSR, implement stream error handling and backpressure.\n- Use `@vue\u002Fserver-renderer`'s `renderToWebStream` for edge runtimes (Cloudflare Workers).\n\n## Latest Vue Patterns\n- **`renderToWebStream`** – for Web Streams API (Node 18+).\n- **`renderToSimpleStream`** – low-level streaming.\n- **`useHydration`** – custom hydration control (experimental).\n\n## Interview Tip\nCompare SSR + hydration to **islands architecture** (Astro, Qwik): Vue's approach hydrates the entire app (unless lazy), while islands only hydrate interactive components. For new projects, consider islands if TTI is critical.\n\n## Common Follow-up\n*\"How do you handle third-party scripts in SSR?\"* – Use `ClientOnly` wrapper to load them only on client, or use `onMounted` to inject `\u003Cscript>` tags.\n\n## Real-world Example\nLazy hydration for a heavy chart component:\n```vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Ch1>Dashboard\u003C\u002Fh1>\n    \u003CLazyHydrate when=\"visible\">\n      \u003Ctemplate #placeholder>\n        \u003Cdiv class=\"chart-placeholder\">Chart loading...\u003C\u002Fdiv>\n      \u003C\u002Ftemplate>\n      \u003CExpensiveChart :data=\"data\" \u002F>\n    \u003C\u002FLazyHydrate>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Advanced Notes\nStreaming SSR works by serialising VNode chunks and writing them to the stream. Async components inside Suspense are tracked; when they resolve, a script is injected to replace the placeholder DOM on client. For partial hydration, Vue provides `createHydrationRenderer` (internal). Edge SSR frameworks like Nuxt Nitro use these primitives to generate static + dynamic islands.",[299,357,226,300,309],"streaming",{"id":50,"category":229,"question":359,"answer":360,"level":324,"tags":361},"How to achieve high-performance rendering in Vue: virtual scrolling, memoization, worker threads, and wasm integration?","## Core Concept\nHigh-performance rendering involves minimising DOM operations, reducing main thread work, and using parallelisation. Techniques include **virtual scrolling** (reducing DOM nodes), **memoisation** (skipping re-renders), **web workers** (offloading computations), and **WebAssembly** (heavy number crunching).\n\n## Virtual Scrolling (Advanced)\n```vue\n\u003Cscript setup>\nimport { ref, computed } from 'vue'\nimport { useVirtualScroll } from '@tanstack\u002Fvue-virtual'\n\nconst items = ref(Array.from({ length: 100000 }, (_, i) => ({ id: i, text: `Item ${i}` })))\nconst parentRef = ref(null)\nconst rowVirtualizer = useVirtualScroll(\n  computed(() => ({\n    size: items.value.length,\n    parentRef: parentRef,\n    estimateSize: () => 35,\n    overscan: 5\n  }))\n)\n\u003C\u002Fscript>\n\u003Ctemplate>\n  \u003Cdiv ref=\"parentRef\" style=\"height: 400px; overflow: auto;\">\n    \u003Cdiv :style=\"{ height: `${rowVirtualizer.getTotalSize()}px` }\">\n      \u003Cdiv\n        v-for=\"virtualRow in rowVirtualizer.getVirtualItems()\"\n        :key=\"virtualRow.key\"\n        :style=\"{ position: 'absolute', top: 0, left: 0, width: '100%', transform: `translateY(${virtualRow.start}px)` }\"\n      >\n        {{ items.value[virtualRow.index].text }}\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Memoization (v-memo + computed caching)\n```vue\n\u003Ctemplate>\n  \u003Cdiv v-for=\"item in hugeList\" :key=\"item.id\" v-memo=\"[item.selected, item.expanded]\">\n    \u003C!-- Expensive subcomponent -->\n    \u003CExpensiveItem :item=\"item\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Web Workers for Computations\n```js\n\u002F\u002F worker.js\nself.onmessage = (e) => {\n  const result = heavyComputation(e.data)\n  postMessage(result)\n}\n\n\u002F\u002F component\nimport { ref, onMounted, onUnmounted } from 'vue'\nconst result = ref(null)\nconst worker = new Worker(new URL('.\u002Fworker.js', import.meta.url))\n\nworker.onmessage = (e) => { result.value = e.data }\nworker.postMessage(largeDataset)\n\nonUnmounted(() => worker.terminate())\n```\n\n## WebAssembly Integration\n```js\n\u002F\u002F Load wasm module\nimport wasmModule from '.\u002Fcompute.wasm'\n\nconst instance = await WebAssembly.instantiate(wasmModule)\nconst { compute } = instance.exports\n\n\u002F\u002F Use in Vue\nconst output = compute(inputArray)\n```\n\n## Execution Flow\n1. Virtual scroll renders only visible rows, reusing DOM nodes.\n2. `v-memo` skips diffing for unchanged items.\n3. Worker thread computes heavy logic without blocking UI.\n4. WASM executes near-native speed for numeric processing.\n\n## Reactivity Explanation\nVirtual scrolling updates the `transform` translation on scroll, triggering re-render of only visible items. `v-memo` prevents reactive dependencies from causing updates.\n\n## Interview Insight\nExplain that virtual scrolling is mandatory for >10k items. `v-memo` is underused – it can dramatically reduce render time for lists with per-item state. Workers are essential for real-time data processing (e.g., filtering large datasets).\n\n## Common Mistakes\n- Virtual scrolling without dynamic row heights – use `@tanstack\u002Fvirtual` which supports dynamic heights.\n- Overusing `v-memo` on small lists – adds overhead.\n- Not terminating workers – memory leaks.\n- Expecting WASM to always be faster – only for numeric\u002Fbitwise operations.\n\n## Best Practices\n- Use `@tanstack\u002Fvue-virtual` for virtual scrolling.\n- Profile before optimising – identify actual bottlenecks.\n- Use `shallowRef` for worker results to avoid deep reactivity overhead.\n- Offload sorting\u002Ffiltering of large arrays to workers.\n\n## Performance Considerations\n- Virtual scroll reduces DOM nodes from O(n) to O(viewport).\n- `v-memo` reduces diff cost from O(n) to O(changed items).\n- Workers use separate threads, no UI blocking.\n- WASM memory is linear; avoid passing large objects back and forth.\n\n## Production Recommendations\n- Use `vue-virtual-scroller` or `@tanstack\u002Fvue-virtual` for stable virtual scrolling.\n- For Web Workers, use `comlink` to simplify RPC.\n- Combine worker + virtual scrolling for huge datasets with filtering.\n\n## Latest Vue Patterns\n- **`@vueuse\u002Fcore\u002FuseWebWorker`** – simplified worker API.\n- **`@vueuse\u002Fcore\u002FuseWebWorkerFn`** – run async function in worker.\n- **`v-memo` with array of dependencies** – fine-grained control.\n\n## Interview Tip\nAsk: \"How would you render 100,000 items with live updates?\" – Virtual scroll for rendering, worker for diffing updates, `v-memo` for stable items, and `shallowRef` for the data array to avoid deep reactivity overhead.\n\n## Common Follow-up\n*\"What is the performance impact of `v-memo` on initial render?\"* – Negligible – it adds a dependency check on each render, but the saved diffing cost outweighs it for large lists.\n\n## Real-world Example\nReal-time stock ticker with 50k symbols:\n```js\n\u002F\u002F worker: calculates price changes\nconst symbols = ref([])\nconst worker = new Worker('.\u002Fticker-worker.js')\nworker.onmessage = (e) => { symbols.value = e.data } \u002F\u002F shallowRef recommended\n```\n\n## Advanced Notes\nVirtual scrolling libraries often need `measureElement` to calculate dynamic heights. `@tanstack\u002Fvirtual` provides that. For WASM, use `@wasm-tool\u002Fwasm-pack-plugin` for Vite. Web Workers can also render HTML using `offscreenCanvas` (advanced). Vue 3's `shallowRef` is key for large worker results – otherwise Vue attempts deep reactivity on the entire array, causing slowdowns.",[183,233,234,362,363],"web-workers","wasm",{"id":57,"category":321,"question":365,"answer":366,"level":324,"tags":367},"Explain custom renderer API and how to build a renderer for non-DOM targets (Canvas, WebGL, native mobile).","## Core Concept\nVue's `createRenderer` API allows creating a custom renderer for any host environment. It decouples the core reactivity and VNode system from the DOM-specific operations. You provide a set of **node operations** (createElement, insert, remove, patchProp, etc.), and the renderer produces render functions for that target.\n\n**Key operations to implement:**\n- `createElement(type)` – create a host node.\n- `createText(text)` – create text node.\n- `setElementText(node, text)` – set text content.\n- `insert(child, parent, anchor)` – insert node.\n- `remove(child)` – remove node.\n- `patchProp(el, key, prevValue, nextValue)` – update property\u002Fattribute.\n- `parentNode(node)` – get parent.\n- `nextSibling(node)` – get next sibling.\n\n## Syntax (Simplified Canvas Renderer)\n```js\nimport { createRenderer } from '@vue\u002Fruntime-core'\n\n\u002F\u002F Canvas context\nconst ctx = canvas.getContext('2d')\n\nconst { render, createApp } = createRenderer({\n  createElement(type) {\n    \u002F\u002F type is 'rect', 'circle', etc.\n    return { type, props: {}, children: [] }\n  },\n  createText(text) {\n    return { type: 'text', text }\n  },\n  insert(child, parent, anchor) {\n    if (anchor) {\n      const index = parent.children.indexOf(anchor)\n      parent.children.splice(index, 0, child)\n    } else {\n      parent.children.push(child)\n    }\n    this.renderNode(child)\n  },\n  patchProp(el, key, prev, next) {\n    el.props[key] = next\n    this.renderNode(el)\n  },\n  \u002F\u002F rendering logic\n  renderNode(node) {\n    if (node.type === 'rect') {\n      ctx.fillStyle = node.props.fill || 'black'\n      ctx.fillRect(node.props.x, node.props.y, node.props.width, node.props.height)\n    }\n    \u002F\u002F ... other shapes\n  }\n})\n\n\u002F\u002F Use like Vue but renders to canvas\nconst app = createApp({\n  data: () => ({ x: 10, y: 10 }),\n  template: '\u003Crect :x=\"x\" :y=\"y\" width=\"50\" height=\"50\" fill=\"red\" \u002F>'\n})\napp.mount(canvas)\n```\n\n## Execution Flow\n1. User creates an app with a template (or render function).\n2. Vue's compiler compiles template to VNode generation code.\n3. When app mounts, renderer calls `createElement` etc. to build host node tree.\n4. On state change, renderer re-renders VNodes, computes diff, and calls patch operations (insert, remove, patchProp).\n5. Host node tree is mutated; your custom logic updates the target (Canvas, Native UI).\n\n## Reactivity Explanation\nReactivity system remains unchanged – only the rendering layer is replaced. The renderer receives reactive VNodes and patches the host tree.\n\n## Practical Usage\n- Rendering to Canvas, WebGL, Three.js.\n- Building native mobile apps with Vue (via NativeScript or custom bindings).\n- Rendering to terminal (CLI apps).\n- Game development with Canvas\u002FWebGL.\n\n## Interview Insight\nExplain that Vue's core is split into `@vue\u002Freactivity` and `@vue\u002Fruntime-core`. The DOM renderer is just one implementation (`@vue\u002Fruntime-dom`). This architecture makes Vue incredibly flexible – you can build renderers for any platform.\n\n## Common Mistakes\n- Not implementing all required operations (e.g., `nextSibling` for fragment support).\n- Assuming DOM-specific APIs exist (e.g., `addEventListener` in Canvas).\n- Forgetting to handle `patchProp` for events and attributes correctly.\n- Not optimising re-renders – Canvas renderer may need diffing at draw level.\n\n## Best Practices\n- Start from `@vue\u002Fruntime-core` and override only necessary methods.\n- Use `createRenderer` with `nodeOps` and `patchProp` separated.\n- For Canvas, batch draw calls after a full render cycle (use `requestAnimationFrame`).\n- Test with simple components before adding complexity.\n\n## Performance Considerations\n- Custom renderers can be more efficient than DOM for certain targets (e.g., Canvas avoids layout\u002Freflow).\n- However, custom diffing may be slower; reuse Vue's VNode diff but implement efficient drawing.\n- Use `shouldUpdateComponent` hooks to skip unnecessary renders.\n\n## Production Recommendations\n- For Canvas, implement a scene graph and only redraw dirty regions.\n- For WebGL, use a library like `three.js` with Vue's reactivity to update matrices.\n- Consider using existing custom renderers (`vue-native`, `vugel`, `vue-threejs`).\n\n## Latest Vue Patterns\n- **`createRenderer`** is stable since Vue 3.0.\n- **`@vue\u002Fruntime-test`** – a test renderer that verifies VNode output.\n- **`@vue\u002Fserver-renderer`** – uses same renderer abstraction for SSR.\n\n## Interview Tip\nExplain that you can also create a **renderer for testing** (like `@vue\u002Fruntime-test`) that outputs serialised VNodes, allowing you to test component logic without a real DOM.\n\n## Common Follow-up\n*\"Can you use the Composition API with a custom renderer?\"* – Yes, fully supported. The renderer only affects the mounting and patching phase; reactivity and component model are unchanged.\n\n## Real-world Example\nMinimal Canvas renderer for a rectangle:\n```js\nconst { render, createApp } = createRenderer({\n  createElement: (type) => ({ type, attrs: {} }),\n  insert: (child, parent) => parent.children.push(child),\n  patchProp: (el, key, _, value) => el.attrs[key] = value,\n  \u002F\u002F ... other required methods\n})\n```\n\n## Advanced Notes\nThe `createRenderer` function returns `{ render, createApp, createAppAPI }`. The `patchProp` function is the most complex – it must handle events (if your target has events), styles, classes, and attributes. For Canvas, you might map `onClick` to canvas coordinates. Vue's reactivity system will still track dependencies in templates; the renderer just outputs drawing commands. For full control, you can also skip templates and use render functions (`h()`) to directly produce VNodes.",[368,369,370,371,336],"custom-renderer","canvas","runtime-core","vnode",{"id":65,"category":373,"question":374,"answer":375,"level":324,"tags":376},"Architecture","How to design a Vue plugin architecture with lifecycle hooks, global injection, and composable APIs?","## Core Concept\nVue plugins are packages that add global-level functionality. A plugin is an object with an `install` method (or a function) that receives the app instance and options. Plugins can register global components, directives, provide\u002Finject values, add instance methods, and extend Vue's behaviour.\n\n## Syntax\n```ts\n\u002F\u002F my-plugin.ts\nimport type { App, Plugin } from 'vue'\n\nexport interface MyPluginOptions {\n  apiUrl: string\n  debug?: boolean\n}\n\nconst MyPlugin: Plugin = {\n  install(app: App, options: MyPluginOptions) {\n    \u002F\u002F 1. Provide global config\n    app.provide('apiUrl', options.apiUrl)\n    app.provide('debug', options.debug ?? false)\n\n    \u002F\u002F 2. Global components\n    app.component('MyButton', MyButton)\n\n    \u002F\u002F 3. Global directives\n    app.directive('focus', { mounted(el) { el.focus() } })\n\n    \u002F\u002F 4. Global properties (use sparingly)\n    app.config.globalProperties.$api = new ApiClient(options.apiUrl)\n\n    \u002F\u002F 5. Custom lifecycle via mixin (Options API) or composable\n    app.mixin({\n      mounted() {\n        console.log('Component mounted from plugin')\n      }\n    })\n\n    \u002F\u002F 6. Add to app config\n    app.config.globalProperties.$myPlugin = { version: '1.0.0' }\n  }\n}\n\n\u002F\u002F Usage in main.ts\nimport { createApp } from 'vue'\nimport MyPlugin from '.\u002Fmy-plugin'\n\nconst app = createApp(App)\napp.use(MyPlugin, { apiUrl: 'https:\u002F\u002Fapi.example.com', debug: true })\n```\n\n## Composable API from Plugin\n```ts\n\u002F\u002F composables\u002FusePlugin.ts\nimport { inject, type Ref } from 'vue'\n\nexport function useMyPlugin() {\n  const apiUrl = inject\u003Cstring>('apiUrl')\n  const debug = inject\u003Cboolean>('debug')\n  if (!apiUrl) throw new Error('Plugin not installed')\n\n  async function fetchData(endpoint: string) {\n    const res = await fetch(`${apiUrl}\u002F${endpoint}`)\n    if (debug) console.log(`Fetched ${endpoint}`)\n    return res.json()\n  }\n\n  return { apiUrl, debug, fetchData }\n}\n```\n\n## Execution Flow\n1. User calls `app.use(MyPlugin, options)`.\n2. Vue calls `MyPlugin.install(app, options)`.\n3. Plugin registers provides, components, directives, etc.\n4. When a component is created, provides are available via `inject`.\n5. Composables (like `useMyPlugin`) are called in components, extracting injected values.\n\n## Practical Usage\n- **UI libraries** – register components globally (e.g., Vuetify, Element Plus).\n- **Auth plugins** – provide user state and login methods.\n- **Analytics** – automatically track page views and events.\n- **i18n** – provide translation function globally.\n\n## Interview Insight\nExplain that plugins should avoid polluting the global namespace – prefer `provide`\u002F`inject` over `globalProperties`. Composables are the modern way to expose plugin APIs. Also note that plugins can be configurable and tree-shakeable if structured properly.\n\n## Common Mistakes\n- Overwriting existing global properties (use Symbols or unique names).\n- Not providing TypeScript types for added global properties (augment `ComponentCustomProperties`).\n- Using `mixin` heavily – leads to naming conflicts; prefer composables.\n- Mutating `app.config` after mounting.\n\n## Best Practices\n- Use `Symbol` or `InjectionKey` for provides to avoid collisions.\n- Augment Vue types for global properties and provides:\n  ```ts\n  declare module '@vue\u002Fruntime-core' {\n    interface ComponentCustomProperties {\n      $api: ApiClient\n    }\n  }\n  ```\n- Provide a composable as the primary API.\n- Support plugin options and allow partial configuration.\n- Check for existing installation to avoid double registration.\n\n## Performance Considerations\n- Global components increase initial bundle size – use tree-shaking if possible.\n- `app.mixin` adds logic to every component, impacting performance; avoid if many components.\n- Provide\u002Finject has negligible cost.\n\n## Production Recommendations\n- For library plugins, export both `install` and individual components\u002Fcomposables for ESM tree-shaking.\n- Document plugin options and exposed APIs.\n- Use `app.version` to check compatibility.\n\n## Latest Vue Patterns\n- **Plugin with `install` returning an object** – for cleanup (rare).\n- **`app.use` chaining** – `app.use(router).use(pinia).use(myPlugin)`.\n- **Async plugins** – plugins can return a promise, but `app.use` does not await; handle async in `install`.\n\n## Interview Tip\nCompare plugin vs composable: plugins are for app-level setup (global), composables are for component-level logic reuse. A plugin can provide composables via injection.\n\n## Common Follow-up\n*\"How do you test a Vue plugin?\"* – Create a new app instance, install the plugin, then assert that components\u002Fdirectives exist, or use `@vue\u002Ftest-utils` to test composables that rely on provides.\n\n## Real-world Example\nSimple analytics plugin:\n```ts\n\u002F\u002F analytics-plugin.ts\nimport { type App } from 'vue'\n\nexport default {\n  install(app: App, options: { trackingId: string }) {\n    \u002F\u002F Load analytics script\n    const script = document.createElement('script')\n    script.src = `https:\u002F\u002Fwww.googletagmanager.com\u002Fgtag\u002Fjs?id=${options.trackingId}`\n    document.head.appendChild(script)\n\n    window.dataLayer = window.dataLayer || []\n    function gtag(...args: any[]) { window.dataLayer.push(args) }\n    gtag('js', new Date())\n    gtag('config', options.trackingId)\n\n    \u002F\u002F Provide method to components\n    app.provide('gtag', gtag)\n    app.config.globalProperties.$gtag = gtag\n  }\n}\n\n\u002F\u002F Usage in component\nconst gtag = inject('gtag')\ngtag('event', 'button_click')\n```\n\n## Advanced Notes\nPlugins can also extend Vue's `App` interface with custom methods: `app.myMethod = () => {}`. For libraries that support both Vue 2 and 3, use `@vue\u002Fcompat` or version detection. The `install` method can be async; however, the app may mount before plugin finishes. To handle async, expose a `ready` promise or use `app.mount` after plugin async work.",[377,13,378,218,379],"plugin","global-api","composable",{"id":74,"category":381,"question":382,"answer":383,"level":324,"tags":384},"Testing","Advanced testing strategies: component testing with Vitest, e2e with Playwright, and mocking composables\u002Fplugins.","## Core Concept\nAdvanced Vue testing involves **unit tests** for composables and utilities (Vitest), **component tests** (Vitest + Vue Test Utils), and **end-to-end tests** (Playwright). Mocking external dependencies (API calls, plugins, global properties) is essential for isolation.\n\n## Component Testing with Vitest\n```ts\n\u002F\u002F MyComponent.spec.ts\nimport { mount } from '@vue\u002Ftest-utils'\nimport { describe, it, expect, vi } from 'vitest'\nimport MyComponent from '.\u002FMyComponent.vue'\n\n\u002F\u002F Mock composable\nvi.mock('@\u002Fcomposables\u002FuseFetch', () => ({\n  useFetch: vi.fn(() => ({\n    data: ref({ name: 'Mocked' }),\n    isLoading: ref(false)\n  }))\n}))\n\ndescribe('MyComponent', () => {\n  it('renders mocked data', async () => {\n    const wrapper = mount(MyComponent)\n    expect(wrapper.text()).toContain('Mocked')\n  })\n\n  it('handles events', async () => {\n    const wrapper = mount(MyComponent)\n    await wrapper.find('button').trigger('click')\n    expect(wrapper.emitted('submit')).toBeTruthy()\n  })\n})\n```\n\n## Mocking Global Plugins\n```ts\n\u002F\u002F test setup\nimport { config } from '@vue\u002Ftest-utils'\nimport { createPinia } from 'pinia'\n\nconfig.global.plugins = [createPinia()]\nconfig.global.provide = {\n  apiUrl: 'https:\u002F\u002Ftest-api.example.com'\n}\nconfig.global.mocks = {\n  $t: (key: string) => key, \u002F\u002F mock i18n\n  $route: { params: { id: '123' } }\n}\n```\n\n## Testing Composables\n```ts\n\u002F\u002F useCounter.spec.ts\nimport { useCounter } from '.\u002FuseCounter'\nimport { describe, it, expect } from 'vitest'\nimport { ref } from 'vue'\n\ndescribe('useCounter', () => {\n  it('increments count', () => {\n    const { count, increment } = useCounter(5)\n    expect(count.value).toBe(5)\n    increment()\n    expect(count.value).toBe(6)\n  })\n})\n```\n\n## Testing Async Composables (with Suspense)\n```ts\nimport { flushPromises } from '@vue\u002Ftest-utils'\nimport { useAsyncData } from '.\u002FuseAsyncData'\n\nit('fetches data', async () => {\n  const { data, loading } = useAsyncData('\u002Fapi\u002Ftest')\n  expect(loading.value).toBe(true)\n  await flushPromises()\n  expect(loading.value).toBe(false)\n  expect(data.value).toBeDefined()\n})\n```\n\n## E2E with Playwright\n```ts\n\u002F\u002F e2e\u002Flogin.spec.ts\nimport { test, expect } from '@playwright\u002Ftest'\n\ntest('login flow', async ({ page }) => {\n  await page.goto('http:\u002F\u002Flocalhost:5173\u002Flogin')\n  await page.fill('input[type=\"email\"]', 'user@example.com')\n  await page.fill('input[type=\"password\"]', 'password')\n  await page.click('button[type=\"submit\"]')\n  await expect(page).toHaveURL('\u002Fdashboard')\n  await expect(page.locator('.welcome')).toContainText('Welcome')\n})\n```\n\n## Execution Flow\n1. Unit\u002Fcomponent tests run in Node with JSDOM (or happy-dom).\n2. Composables are tested directly, without component mounting.\n3. Component tests mount components, simulate user interactions, assert DOM and emitted events.\n4. E2E tests run in real browser, testing full integration.\n\n## Reactivity Explanation\nIn tests, reactivity works normally because Vue's runtime is fully loaded. `flushPromises` ensures all microtasks (like `nextTick`) are resolved.\n\n## Interview Insight\nExplain that testing composables is often easier than testing components because they are pure functions (with reactivity). For components, prefer testing behaviour (user interactions, emitted events) over implementation details.\n\n## Common Mistakes\n- Not awaiting async operations (e.g., `trigger('click')` may trigger async updates).\n- Testing internal state instead of user-visible output.\n- Mocking too much – leads to false positives.\n- Not cleaning up between tests (global mocks persist).\n\n## Best Practices\n- Use `@vue\u002Ftest-utils` `mount` for components, `shallowMount` for isolation.\n- Mock network requests with `vi.mock` or MSW (Mock Service Worker).\n- Use `vi.useFakeTimers` for testing debounce\u002Fthrottle.\n- For composables, test in a `withSetup` helper that creates a component scope.\n\n## Performance Considerations\n- Component tests are slower than unit tests; batch them or use `shallowMount`.\n- Use `vitest` watch mode for fast feedback.\n- Parallelise e2e tests.\n\n## Production Recommendations\n- Use `vitest` + `@vue\u002Ftest-utils` for unit\u002Fcomponent tests.\n- Use `playwright` for e2e – supports multiple browsers.\n- Use `@vitejs\u002Fplugin-vue` for test environment.\n- Set `test.globals: true` in Vitest for convenience.\n\n## Latest Vue Patterns\n- **`@vue\u002Ftest-utils` v2** – supports Vue 3.\n- **`createTestingPinia`** – for testing Pinia stores.\n- **`@vitest\u002Fcoverage-v8`** – code coverage.\n\n## Interview Tip\nExplain how to test a component that uses `provide\u002Finject`: use `global.provide` in mount options, or wrap it in a provider component.\n\n## Common Follow-up\n*\"How do you test a component with `v-model`?\"* – Use `wrapper.setValue()` on input, then assert emitted `update:modelValue` event, or use `wrapper.vm.modelValue` if exposed.\n\n## Real-world Example\nTesting a form component with async validation:\n```ts\nimport { mount } from '@vue\u002Ftest-utils'\nimport { describe, it, expect, vi } from 'vitest'\nimport RegistrationForm from '.\u002FRegistrationForm.vue'\n\nvi.mock('@\u002Fapi', () => ({\n  checkEmail: vi.fn(() => Promise.resolve({ available: true }))\n}))\n\nit('validates email asynchronously', async () => {\n  const wrapper = mount(RegistrationForm)\n  await wrapper.find('input[name=\"email\"]').setValue('test@example.com')\n  await wrapper.find('form').trigger('submit')\n  await flushPromises()\n  expect(wrapper.emitted('success')).toBeTruthy()\n})\n```\n\n## Advanced Notes\nFor testing components with `\u003CSuspense>`, use `mount` with `attachTo: document.body` and await `flushPromises`. For testing `onErrorCaptured`, trigger errors in child components. For custom renderers, you can test using `@vue\u002Fruntime-test` renderer. E2E tests can intercept network requests using Playwright's `page.route`. Mock service workers (MSW) can be used for both component tests and e2e to share mocks.",[385,386,387,388,389],"testing","vitest","playwright","mocking","vue-test-utils",{"id":83,"category":122,"question":391,"answer":392,"level":324,"tags":393},"What is Reactivity Transform and why was it deprecated? Explain the `$ref` and `$computed` macros.","## Core Concept\nReactivity Transform was an experimental feature in Vue 3.2-3.4 that allowed using `$ref` and `$computed` to eliminate the `.value` boilerplate in Composition API. It was a compile-time transform that rewrote `$ref` to `ref()` and automatically added `.value` accesses.\n\n**Why deprecated:** It added too much magic, hurt TypeScript inference in some cases, and required specific build tooling. The team decided to focus on other improvements (like `defineModel` and `toValue`) instead.\n\n## Syntax (if still available)\n```vue\n\u003Cscript setup>\n\u002F\u002F With Reactivity Transform (deprecated)\nlet count = $ref(0)\nconst double = $computed(() => count * 2)\nfunction increment() { count++ }  \u002F\u002F compiles to count.value++\n\n\u002F\u002F Without transform (standard)\nimport { ref, computed } from 'vue'\nlet count = ref(0)\nconst double = computed(() => count.value)\nfunction increment() { count.value++ }\n\u003C\u002Fscript>\n```\n\n## Execution Flow\n1. Compiler scans for `$ref` and `$computed` calls.\n2. Replaces `$ref(0)` with `ref(0)` and stores variable name.\n3. Rewrites all accesses to `count` to `count.value` (except when used in template).\n4. Generates standard Vue 3 code.\n\n## Interview Insight\nExplain that Reactivity Transform is now **deprecated** and not recommended for new projects. The team's official stance is that `.value` is a good explicit marker of reactivity. However, understanding it shows awareness of Vue's evolution.\n\n## Common Mistakes\n- Using `$ref` in a project without the transform plugin – runtime error.\n- Expecting TypeScript to understand `$ref` without special config.\n- Mixing `$ref` and normal `ref` inconsistently.\n\n## Best Practices\n- Stick to standard `ref` with `.value` for clarity and compatibility.\n- If you dislike `.value`, consider using `reactive` for objects.\n- For new projects, ignore Reactivity Transform.\n\n## Performance Considerations\nThe transform had no runtime impact – it was purely compile-time. Standard `ref` has identical performance.\n\n## Production Recommendations\n- Do not enable Reactivity Transform in production code.\n- Migrate existing transform code using codemods.\n\n## Latest Vue Patterns\n- **`toValue`** – unwraps refs and getters (preferred alternative).\n- **`defineModel`** – eliminates some `.value` in two-way bindings.\n\n## Interview Tip\nIf asked about Reactivity Transform, acknowledge its deprecation but show you understand the problem it tried to solve: reducing `.value` noise.\n\n## Real-world Example\nCodemod to migrate away from `$ref`:\n```js\n\u002F\u002F Before\nlet count = $ref(0)\ncount++\n\u002F\u002F After\nlet count = ref(0)\ncount.value++\n```\n\n## Advanced Notes\nThe transform also supported `$raw` to escape the transform, and `$fromRefs` to convert an object of refs. The feature was removed in Vue 3.5; `@vue\u002Fcomposition-api` for Vue 2 still has it as an option.",[394,126,395,134],"reactivity-transform","deprecated",{"id":93,"category":321,"question":397,"answer":398,"level":324,"tags":399},"How does Vue Devtools integration work? Explain the custom inspection API and performance profiling hooks.","## Core Concept\nVue Devtools communicates with a Vue app via a global `__VUE_DEVTOOLS_GLOBAL_HOOK__` event bus. Vue core emits events (component mount, update, unmount, performance marks) that Devtools listens to. Custom inspection allows plugins and components to expose additional data.\n\n## Key Integration Points\n- **`app.config.performance = true`** – enables performance marks for render timing.\n- **`devtools` plugin** – registers custom formatters for state inspection.\n- **`describe`** – custom inspection API for components.\n\n## Syntax\n```js\n\u002F\u002F Enable performance tracking in main.js\nconst app = createApp(App)\napp.config.performance = true\n\n\u002F\u002F Custom inspection for a component\n\u003Cscript setup>\nimport { getCurrentInstance } from 'vue'\nconst instance = getCurrentInstance()\nif (process.env.NODE_ENV === 'development') {\n  instance?.devtoolsRawSetupState = {\n    \u002F\u002F Expose internal state to Devtools\n    customData: myReactiveData\n  }\n}\n\u003C\u002Fscript>\n```\n\n## Devtools Plugin API\n```js\n\u002F\u002F my-devtools-plugin.js\nimport { setupDevtoolsPlugin } from '@vue\u002Fdevtools-api'\n\nsetupDevtoolsPlugin({\n  id: 'my-plugin',\n  label: 'My Plugin',\n  packageName: 'my-plugin',\n  homepage: '...',\n  componentStateTypes: ['my-custom-type']\n}, (api) => {\n  api.on.inspectComponent((payload, ctx) => {\n    payload.instanceData.state.push({\n      type: 'my-custom-type',\n      key: 'custom',\n      value: 'some value',\n      editable: false\n    })\n  })\n})\n```\n\n## Execution Flow\n1. Vue app initialisation checks for `window.__VUE_DEVTOOLS_GLOBAL_HOOK__`.\n2. If exists, Vue emits `'init'` event with the app instance.\n3. Devtools captures the app and starts sending inspection queries.\n4. On component mount\u002Fupdate, Vue emits `'mount'` and `'update'` events.\n5. Devtools refreshes component tree and state.\n6. Performance marks (`'render-start'`, `'render-end'`) are captured if `performance: true`.\n\n## Reactivity Explanation\nDevtools itself is not reactive – it reads snapshots of reactive state when user inspects components.\n\n## Interview Insight\nExplain that Devtools integration is **opt-in** and adds minimal overhead in development. It's essential for debugging large apps. The custom inspection API allows libraries (Pinia, Vue Router) to show their state beautifully.\n\n## Common Mistakes\n- Leaving `app.config.performance = true` in production – adds overhead.\n- Expecting Devtools to show all private state – only exposed via devtoolsRawSetupState.\n- Forgetting to include `@vue\u002Fdevtools-api` for custom plugins.\n\n## Best Practices\n- Enable performance only in development (e.g., using `import.meta.env.DEV`).\n- Use Devtools custom formatters for custom data structures.\n- For library authors, integrate with Devtools via plugin API.\n\n## Performance Considerations\n- Devtools adds event listeners and serialisation overhead; only enable in dev.\n- Performance marks add small overhead; still fine for debugging.\n\n## Production Recommendations\n- Never bundle Devtools API in production – use conditional imports.\n- Remove `app.config.performance` in production builds.\n\n## Latest Vue Patterns\n- **`@vue\u002Fdevtools-api`** – stable API for plugin authors.\n- **Vue Devtools v6** – supports Vue 3, Composition API, Pinia, and custom inspectors.\n- **Timeline events** – custom plugins can add timeline entries.\n\n## Interview Tip\nMention that you can also use `window.$vue` in Devtools console to inspect component instances (if enabled).\n\n## Common Follow-up\n*\"Can you inspect Pinia stores in Devtools?\"* – Yes, Pinia registers its own Devtools plugin to show state, getters, and actions.\n\n## Real-world Example\nCustom Devtools inspector for a GraphQL cache:\n```js\nsetupDevtoolsPlugin({ id: 'apollo-cache' }, (api) => {\n  api.addTimelineLayer({ id: 'apollo', label: 'Apollo Queries', color: 0x8e44ad })\n  \u002F\u002F on cache write, add timeline event\n  api.addTimelineEvent({ layerId: 'apollo', event: { title: 'Query executed', time: Date.now() } })\n})\n```\n\n## Advanced Notes\nThe Devtools protocol uses `window.postMessage` to communicate between Vue app and Devtools extension. The global hook also supports `__VUE_DEVTOOLS_DISABLE__` to opt-out. For Electron or non-browser environments, you can use `@vue\u002Fdevtools` standalone server.",[400,401,183,402],"devtools","debugging","inspection",{"id":103,"category":229,"question":404,"answer":405,"level":324,"tags":406},"What are memory optimization techniques in Vue: avoiding leaks, `shallowRef`, `markRaw`, and manual cleanup?","## Core Concept\nMemory leaks in Vue often come from uncleaned event listeners, interval timers, observables, and large reactive objects. Optimisations include using `shallowRef` (reduces proxy overhead), `markRaw` (prevents reactivity on large static data), and manual cleanup in `onUnmounted`.\n\n## Techniques\n```vue\n\u003Cscript setup>\nimport { ref, shallowRef, markRaw, onUnmounted, reactive } from 'vue'\n\n\u002F\u002F 1. Use shallowRef for large arrays that replace entirely\nconst largeTable = shallowRef([])\n\u002F\u002F Update: replace whole array, not mutate\nlargeTable.value = await fetchLargeDataset()\n\n\u002F\u002F 2. Mark raw for static data that never needs reactivity\nconst staticConfig = markRaw({ apiKey: '123', timeout: 5000 })\n\n\u002F\u002F 3. Avoid deep reactivity on large nested objects\nconst profile = shallowReactive({ user: { name: 'Alice' } }) \u002F\u002F only user property is reactive, not name\n\n\u002F\u002F 4. Clean up event listeners\nlet resizeHandler = () => { console.log(window.innerWidth) }\nonMounted(() => window.addEventListener('resize', resizeHandler))\nonUnmounted(() => window.removeEventListener('resize', resizeHandler))\n\n\u002F\u002F 5. Clean up intervals\nconst interval = setInterval(() => {}, 1000)\nonUnmounted(() => clearInterval(interval))\n\n\u002F\u002F 6. Use WeakMap\u002FWeakSet for caching\nconst cache = new WeakMap()\n\n\u002F\u002F 7. Avoid circular references in reactive objects\nconst parent = reactive({ children: [] })\nconst child = reactive({ parent }) \u002F\u002F circular – use markRaw on one side\nparent.children.push(markRaw(child))\n\u003C\u002Fscript>\n```\n\n## Execution Flow\n1. Normal `ref` of a large object creates a deep Proxy, wrapping every nested object.\n2. `shallowRef` only wraps the top-level `.value` – nested objects remain plain.\n3. `markRaw` sets a flag (`__v_skip`) that prevents Proxy conversion.\n4. Event listeners keep DOM references; remove them to allow GC.\n\n## Reactivity Explanation\nMemory leaks happen when Vue holds references to components or DOM nodes after unmount. Proxies themselves are lightweight, but the objects they wrap cannot be GC'd if any reactive effect still references them.\n\n## Interview Insight\nExplain that Vue's reactivity system uses `WeakMap` for `targetMap`, so unreachable reactive objects are garbage-collected. However, event listeners, intervals, and external libraries can still leak. `shallowRef` is often overlooked but crucial for large datasets.\n\n## Common Mistakes\n- Not cleaning up `addEventListener` in `onUnmounted`.\n- Storing large data in `reactive` when only replacements are needed (use `shallowRef`).\n- Using `ref` for huge immutable data (e.g., 100MB logs).\n- Keeping references to DOM elements after unmount.\n\n## Best Practices\n- Profile memory with Chrome DevTools memory snapshots.\n- Use `shallowRef` for arrays >10k items.\n- Use `markRaw` for static configuration and third-party instances.\n- Always pair `onMounted` setup with `onUnmounted` cleanup.\n\n## Performance Considerations\n- `shallowRef` reduces memory (no nested proxies) and speeds up initial render.\n- `markRaw` eliminates all reactivity overhead for that object.\n- Proper cleanup prevents incremental memory growth in long-running SPAs.\n\n## Production Recommendations\n- Monitor memory usage in production using `performance.memory` or monitoring tools.\n- For infinite scroll pages, clear old data from arrays and use `shallowRef`.\n- Use `WeakRef` and `FinalizationRegistry` for advanced caching (rare).\n\n## Latest Vue Patterns\n- **`shallowReactive`** – similar to `shallowRef` but for object properties.\n- **`toRaw`** – get original object and unref it, break reactivity manually.\n- **`effectScope`** – group effects and stop them all at once.\n\n## Interview Tip\nAsk: \"How would you handle a real-time WebSocket feed with 100k messages?\" – Use `shallowRef` for the array, push new messages, and periodically trim old ones using `array.shift()` (which will trigger update, but cheap because array is shallow).\n\n## Common Follow-up\n*\"Does `shallowRef` make the array content reactive?\"* – No. The array itself is reactive (reassignment triggers update), but individual objects inside are not. To update an object, you need to replace the whole array or use a new reference.\n\n## Real-world Example\nChat app with message history:\n```ts\nconst messages = shallowRef\u003CMessage[]>([])\n\nfunction addMessage(msg: Message) {\n  messages.value = [...messages.value, msg] \u002F\u002F triggers update\n  if (messages.value.length > 10000) {\n    messages.value = messages.value.slice(-5000) \u002F\u002F keep last 5000\n  }\n}\n```\n\n## Advanced Notes\nVue's `markRaw` is irreversible – once marked, the object will never be made reactive. Use it for constants, libraries, or large read-only data. For circular references in JSON data, you can use `markRaw` on the circular edge. The `targetMap` (WeakMap) ensures that when a reactive object has no references, its dependency tracking is removed.",[407,181,182,204,183],"memory",{"id":112,"category":409,"question":410,"answer":411,"level":324,"tags":412},"Security","What are security patterns in Vue: preventing XSS, safe HTML binding, CSRF protection, and content security policies?","## Core Concept\nVue automatically escapes interpolated content (`{{ }}`) to prevent XSS (Cross-Site Scripting). However, `v-html` bypasses escaping and can be dangerous. Other security concerns include dynamic component names, `:src` bindings, and handling user input in event handlers.\n\n## XSS Prevention\n```vue\n\u003Ctemplate>\n  \u003C!-- Safe: escaped automatically -->\n  \u003Cdiv>{{ userInput }}\u003C\u002Fdiv>\n\n  \u003C!-- Dangerous: unsanitized HTML rendering -->\n  \u003Cdiv v-html=\"userHtml\" \u002F>  \u003C!-- ❌ risk -->\n\n  \u003C!-- Safer alternative: sanitize first -->\n  \u003Cdiv v-html=\"sanitizedHtml\" \u002F>\n\n  \u003C!-- Dynamic attribute names: also risky -->\n  \u003Ca :[attributeName]=\"url\">Link\u003C\u002Fa>  \u003C!-- ❌ if attributeName is user-controlled -->\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport DOMPurify from 'dompurify'\nconst userHtml = ref('\u003Cimg src=x onerror=alert(1)>')\nconst sanitizedHtml = computed(() => DOMPurify.sanitize(userHtml.value))\n\u003C\u002Fscript>\n```\n\n## CSRF Protection\n```js\n\u002F\u002F For traditional API endpoints (not recommended for SPA token-based auth)\n\u002F\u002F Use CSRF token in meta tag\n\u002F\u002F \u003Cmeta name=\"csrf-token\" content=\"...\">\n\nconst csrfToken = document.querySelector('meta[name=\"csrf-token\"]')?.content\nfetch('\u002Fapi\u002Fdata', {\n  method: 'POST',\n  headers: { 'X-CSRF-Token': csrfToken },\n  credentials: 'same-origin'\n})\n\n\u002F\u002F Better: use token-based auth (JWT) with HTTP-only cookies or Bearer tokens\n```\n\n## Content Security Policy (CSP)\n```html\n\u003C!-- index.html -->\n\u003Cmeta http-equiv=\"Content-Security-Policy\" content=\"\n  default-src 'self';\n  script-src 'self' 'nonce-abc123';\n  style-src 'self' 'unsafe-inline';\n\">\n```\n\n## Safe Dynamic Components\n```vue\n\u003Ctemplate>\n  \u003C!-- Only allow whitelisted component names -->\n  \u003Ccomponent :is=\"allowedComponent\" \u002F>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nconst componentMap = {\n  MySafeComponent,\n  AnotherSafeComponent\n}\nconst userSelection = ref('MySafeComponent')\nconst allowedComponent = computed(() => componentMap[userSelection.value] || null)\n\u003C\u002Fscript>\n```\n\n## Execution Flow\n1. Vue template compiler escapes any content inside `{{ }}` by encoding HTML entities.\n2. `v-html` outputs raw HTML – Vue does **not** sanitise.\n3. Dynamic `:is` accepts any component definition – malicious user input could load arbitrary components.\n4. Event handlers (e.g., `@click`) are safe because they run in component context, not `eval`.\n\n## Interview Insight\nExplain that Vue's default behaviour is XSS-safe, but developers must be careful with `v-html`, dynamic component names, and dynamic `:href`\u002F`:src` bindings. Also mention that Vue's reactivity does not introduce new vulnerabilities beyond standard web security.\n\n## Common Mistakes\n- Using `v-html` on user-generated content without sanitisation.\n- Allowing user input to control `:is` or `:href` with `javascript:` protocol.\n- Storing sensitive data in `localStorage` without encryption.\n- Disabling CSP `unsafe-inline` for styles but not for scripts.\n\n## Best Practices\n- Use `DOMPurify` or similar library for any `v-html` with user input.\n- Never use `v-html` on rich text editor output without sanitisation.\n- Use a whitelist for dynamic component names and URLs.\n- Set `Content-Security-Policy` headers.\n- Use `:href` with `javascript:` validation (or better, avoid it).\n\n## Performance Considerations\n- Sanitisation libraries add small overhead; debounce if needed.\n- CSP `nonce` or `hash` may affect performance if scripts are large.\n\n## Production Recommendations\n- Use `helmet` on server to set CSP headers.\n- For rich text, use a dedicated editor that outputs sanitised HTML.\n- Never disable security warnings in production.\n\n## Latest Vue Patterns\n- **Vue 3.4+** – improved warning for dynamic component with raw string.\n- **`useSanitize` composable** – abstract sanitisation logic.\n\n## Interview Tip\nExplain the concept of **trusted types** (CSP `require-trusted-types-for`) that can help prevent DOM XSS. Vue itself can comply with trusted types.\n\n## Common Follow-up\n*\"Can Vue’s template compiler be bypassed?\"* – Only through `v-html` or dynamic `:innerHTML` bindings. Also, `:` binding to `href` with `javascript:` is still dangerous if user controls the value.\n\n## Real-world Example\nSafe rendering of user comments:\n```vue\n\u003Ctemplate>\n  \u003Cdiv v-for=\"comment in comments\" :key=\"comment.id\">\n    \u003C!-- Escaped text -->\n    \u003Cp>{{ comment.author }}: \u003C\u002Fp>\n    \u003C!-- Sanitised HTML for markdown -->\n    \u003Cdiv v-html=\"sanitizeMarkdown(comment.text)\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport DOMPurify from 'dompurify'\nimport { marked } from 'marked'\nconst sanitizeMarkdown = (text) => DOMPurify.sanitize(marked.parse(text))\n\u003C\u002Fscript>\n```\n\n## Advanced Notes\nFor high-security apps, consider using `@vue\u002Fcompiler-dom` with custom directive to forbid `v-html`. Also, Vue's `v-pre` can skip compilation but does not introduce security issues. For CSP with `nonce`, Vue requires inline script tags to have the nonce attribute; you can set `app.config.compilerOptions.isCustomElement` to avoid CSP violations. Server-side rendering also needs CSP considerations for inline styles and scripts.",[413,414,415,416,417],"security","xss","csp","csrf","sanitization",{"id":121,"category":373,"question":419,"answer":420,"level":324,"tags":421},"How to implement micro frontends with Vue? Discuss Module Federation, single-spa, and Web Components.","## Core Concept\nMicro frontends split a large application into smaller, independently deployable frontend applications. Vue can be used as a micro frontend via **Module Federation** (sharing code between builds), **single-spa** (orchestrating frameworks), or by compiling Vue components to **Web Components** (framework-agnostic).\n\n## Module Federation (Webpack\u002FVite)\n```js\n\u002F\u002F webpack.config.js (host app)\nnew ModuleFederationPlugin({\n  name: 'host',\n  remotes: {\n    vue_app: 'vue_app@http:\u002F\u002Flocalhost:3001\u002FremoteEntry.js'\n  }\n})\n\n\u002F\u002F Dynamically load remote component\nconst RemoteButton = defineAsyncComponent(() => import('vue_app\u002FButton'))\n```\n\n## single-spa Integration\n```js\n\u002F\u002F root config\nimport { registerApplication, start } from 'single-spa'\n\nregisterApplication({\n  name: 'vue-microfrontend',\n  app: () => import('.\u002Fvue-app\u002Fmain.js'),\n  activeWhen: ['\u002Fvue']\n})\n\nstart()\n\n\u002F\u002F vue-app\u002Fmain.js\nimport { createApp } from 'vue'\nimport singleSpaVue from 'single-spa-vue'\n\nconst vueLifecycles = singleSpaVue({ createApp, appOptions: { render: () => h(App) } })\nexport const { bootstrap, mount, unmount } = vueLifecycles\n```\n\n## Vue Web Components\n```js\n\u002F\u002F Component that becomes a custom element\nimport { defineCustomElement } from 'vue'\nimport MyWidget from '.\u002FMyWidget.vue'\n\nconst MyWidgetCE = defineCustomElement(MyWidget)\ncustomElements.define('my-widget', MyWidgetCE)\n\n\u002F\u002F Use in any framework\n\u003Cmy-widget :some-prop=\"value\">\u003C\u002Fmy-widget>\n```\n\n## Execution Flow\n1. **Module Federation:** Host loads remote entry, remote module code is fetched at runtime.\n2. **single-spa:** Root listens to URL, mounts\u002Funmounts Vue apps.\n3. **Web Components:** Vue component compiled to native custom element, uses Shadow DOM by default.\n\n## Reactivity Explanation\nReactivity stays inside each Vue app instance. In Module Federation, separate Vue runtimes may conflict – ensure single shared Vue version. In single-spa, each app has its own Vue instance. Web Components are framework-agnostic – no cross-app reactivity.\n\n## Interview Insight\nExplain that micro frontends add complexity; only use for large orgs with multiple teams. Module Federation is best for sharing code between apps. single-spa is mature but requires careful CSS isolation. Web Components are simplest but lose Vue-specific optimisations (e.g., slot distribution).\n\n## Common Mistakes\n- Not isolating CSS – styles from one app leak to another.\n- Using different Vue versions across apps – causes hydration\u002Fruntime conflicts.\n- Expecting two-way binding across app boundaries (use events or global store).\n- Over-optimising – not all apps need micro frontends.\n\n## Best Practices\n- Share a single Vue version via Module Federation.\n- Use CSS Modules or Shadow DOM for style isolation.\n- Use custom events for cross-app communication.\n- Lazy load micro frontends to reduce initial bundle.\n\n## Performance Considerations\n- Each app has its own Vue instance overhead.\n- Module Federation adds network requests for remote modules.\n- Web Components have Shadow DOM performance cost.\n\n## Production Recommendations\n- Use `vite-plugin-federation` for Module Federation with Vite.\n- Use `single-spa` with `import-map-overrides` for dynamic deployment.\n- For Web Components, use `defineCustomElement` with `shadowRoot: true` (default).\n\n## Latest Vue Patterns\n- **`@originjs\u002Fvite-plugin-federation`** – Vite version of Module Federation.\n- **`single-spa-vue` v5** – supports Vue 3.\n- **`vue-loader` custom element mode** – compile SFC to custom elements.\n\n## Interview Tip\nExplain that Vue 3's `defineCustomElement` uses Vue's runtime but creates a standalone custom element, perfect for distributing Vue components to non-Vue teams.\n\n## Common Follow-up\n*\"How do you share state between micro frontends?\"* – Use a global event bus (`window.dispatchEvent`), a shared store like `redux` or `Pinia` with Module Federation, or URL parameters.\n\n## Real-world Example\nHost app that loads a Vue micro frontend:\n```js\n\u002F\u002F host\u002Fsrc\u002Fmain.js\nimport { defineAsyncComponent } from 'vue'\n\nconst VueMicroApp = defineAsyncComponent(() => import('vue_mfe\u002FApp'))\n\n\u002F\u002F In template\n\u003CVueMicroApp :userId=\"currentUser.id\" @logout=\"handleLogout\" \u002F>\n```\n\n## Advanced Notes\nFor server-side rendering with micro frontends, use `single-spa` with `ssr` mode or fragment composition. Module Federation can also share `pinia` stores, but be cautious with global state conflicts. Web Components from Vue can be server-rendered using `@vue\u002Fserver-renderer` with custom element detection.",[422,423,424,425,13],"micro-frontends","module-federation","single-spa","web-components",{"id":129,"category":373,"question":427,"answer":428,"level":324,"tags":429},"What are production scaling patterns for Vue: monorepos, dynamic imports, composable libraries, and design systems?","## Core Concept\nScaling Vue applications involves **monorepo** management (multiple packages), **dynamic imports** for code splitting, **composable libraries** for sharing logic, and **design systems** for UI consistency. Tools like Nx, Turborepo, or pnpm workspaces enable efficient monorepo development.\n\n## Monorepo Structure (pnpm workspace)\n```\nmy-vue-app\u002F\n  packages\u002F\n    apps\u002F\n      web\u002F          # main Vue app\n      admin\u002F        # admin dashboard\n    shared\u002F\n      ui\u002F           # design system components\n      composables\u002F  # shared composables\n      utils\u002F        # shared utilities\n    config\u002F\n      eslint\u002F       # shared config\n      typescript\u002F   # shared tsconfig\n```\n\n## Dynamic Imports for Routes\n```js\n\u002F\u002F router\u002Findex.js\nconst routes = [\n  {\n    path: '\u002Fdashboard',\n    component: () => import(\u002F* webpackChunkName: \"dashboard\" *\u002F '..\u002Fviews\u002FDashboard.vue')\n  },\n  {\n    path: '\u002Fadmin',\n    component: () => import(\u002F* webpackPrefetch: true *\u002F '..\u002Fviews\u002FAdmin.vue')\n  }\n]\n```\n\n## Composable Library\n```ts\n\u002F\u002F packages\u002Fcomposables\u002Fsrc\u002FuseFetch.ts\nexport function useFetch\u003CT>(url: MaybeRefOrGetter\u003Cstring>) {\n  \u002F\u002F ... composable implementation\n}\n\n\u002F\u002F packages\u002Fcomposables\u002Findex.ts\nexport { useFetch } from '.\u002Fsrc\u002FuseFetch'\n\u002F\u002F Published as @myorg\u002Fcomposables\n```\n\n## Design System with Vue\n```vue\n\u003C!-- packages\u002Fui\u002Fsrc\u002FButton.vue -->\n\u003Cscript setup lang=\"ts\">\ndefineProps\u003C{ variant?: 'primary' | 'secondary'; size?: 'sm' | 'md' | 'lg' }>()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cbutton :class=\"[`btn-${variant}`, `btn-${size}`]\">\n    \u003Cslot \u002F>\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003C!-- Usage in app -->\n\u003CButton variant=\"primary\">Click\u003C\u002FButton>\n```\n\n## Execution Flow\n1. Monorepo tools link local packages without publishing.\n2. Build system compiles each package independently.\n3. Applications import from shared packages as if they were external.\n4. Vite\u002FWebpack bundle only used code (tree-shaking).\n5. Dynamic chunks loaded on demand.\n\n## Interview Insight\nExplain that scaling is not just about performance but also team organisation. Monorepos enable code reuse and standardisation. Design systems reduce duplication. Composable libraries abstract logic that would otherwise be copied.\n\n## Common Mistakes\n- Monorepo without proper tooling (slow builds, dependency hell).\n- Over-splitting – too many packages create overhead.\n- Not versioning shared packages – breaking changes affect all apps.\n- Ignoring tree-shaking – design system may include unused components.\n\n## Best Practices\n- Use `pnpm` or `yarn workspaces` for monorepo.\n- Use `vite` with `build.lib` for composable libraries.\n- Use `unplugin-vue-components` for auto-importing design system components.\n- Use `changesets` for versioning.\n- Lint and test shared packages independently.\n\n## Performance Considerations\n- Monorepo builds can be slower; use caching (Turborepo, Nx).\n- Dynamic imports reduce initial bundle size.\n- Design system components should be tree-shakeable (sideEffects: false).\n\n## Production Recommendations\n- Use `vite-plugin-dts` to generate .d.ts for TypeScript libraries.\n- Publish composable libraries to private npm registry.\n- Use `npm pack` or `pnpm pack` for local testing.\n\n## Latest Vue Patterns\n- **`unplugin-vue-components`** – auto-import Vue components from design system.\n- **`vite-plugin-lib-inject-css`** – inject CSS for component libraries.\n- **`@vue\u002Ftsconfig`** – shared TypeScript config.\n\n## Interview Tip\nExplain the difference between monorepo and multi-repo: monorepo suits tightly coupled apps, multi-repo for independent teams. For Vue, monorepo with pnpm is very popular (used by Nuxt, Vite).\n\n## Common Follow-up\n*\"How do you handle shared state across packages in monorepo?\"* – Use Pinia stores exported from a shared package. But be aware that stores become singletons per app; if you need cross-app state, use a global event bus or custom solution.\n\n## Real-world Example\nDesign system with auto-import:\n```ts\n\u002F\u002F vite.config.ts\nimport Components from 'unplugin-vue-components\u002Fvite'\n\nexport default {\n  plugins: [\n    Components({\n      dirs: ['packages\u002Fui\u002Fsrc\u002Fcomponents'],\n      dts: 'components.d.ts'\n    })\n  ]\n}\n```\n\n## Advanced Notes\nFor large monorepos, use **Nx** or **Turborepo** for task orchestration. They support `vite` and `vue`. For **module federation** across apps in monorepo, you can still use `@originjs\u002Fvite-plugin-federation`. For **design systems**, consider using `histoire` or `storybook` for component documentation. For **composable libraries**, export `Ref` types and ensure they are compatible with target Vue version.",[430,227,431,201,432],"monorepo","design-system","scaling",1779734543422]