In Vue 3, when a v-if/v-else pair renders an <input> in each branch, does typed text survive switching branches, and why?
answer
- same tag, different branch
- keys you did not write
- Vue 2 reused the element
- manual keys must differ
basics
~20 sNo. Vue 3's compiler gives every v-if, v-else-if and v-else branch its own automatic key, so switching branches unmounts one input and mounts a fresh one; Vue 2 reused same-tag elements unless you added keys.
solid answer
~40 sNo, the text is discarded. Vue 3's template compiler **auto-generates a unique key per branch** of a `v-if` / `v-else-if` / `v-else` chain, so two `<input>` elements in different branches are never treated as the same node: the old one is unmounted and a new one is mounted. In **Vue 2** the same-tag element was patched in place, and the typed value carried over unless you added distinct keys. You can still write keys on branches, but each must be **unique** (the compiler reports `v-if/else branches must use unique keys.`), so the Vue 2 trick of sharing one key to force reuse is gone. The chain itself has rules: `v-else-if` and `v-else` must immediately follow a `v-if` or `v-else-if` sibling, and a `<template>` can carry any branch to toggle several elements at once.
go deeper
Know the v-if, v-else-if and v-else chain, that branches must be adjacent, and that <template> can carry a branch.
Explain that Vue 3 keys each branch automatically, so same-tag elements in different branches are separate nodes and lose DOM state.
Recognise Vue 2 key workarounds during upgrades, remove or de-duplicate them, and make intended value persistence explicit with bound state.
Treat DOM-held state as disposable across conditional branches and keep anything that must survive a switch in component or store state.
## The chain and its rules A conditional chain is a `v-if` followed by any number of `v-else-if` siblings and at most one `v-else`: ```vue-html <p v-if="status === 'loading'">Loading…</p> <p v-else-if="status === 'error'">Failed</p> <template v-else> <h2>{{ title }}</h2> <p>{{ body }}</p> </template> ``` The compiler checks a few rules: - **Adjacency**: a `v-else-if` or `v-else` must come right after a `v-if` or `v-else-if` sibling. Whitespace and comments in between are tolerated; another element is not, and the compiler reports `v-else/v-else-if has no adjacent v-if or v-else-if.` - **`<template>` branches**: any branch may be a `<template>` so it can switch a group of elements without adding a wrapper to the DOM. - **At most one branch renders.** When none matches and there is no `v-else`, a comment placeholder stands in its place. ## Branch identity: auto-generated keys When the condition flips, Vue compares the vnode it rendered last time with the one it renders now. Two vnodes are treated as the same node only if their **type and key** match. Vue 3's compiler assigns each branch of a chain a **distinct key** automatically, based on its position in the chain, unless you wrote one yourself. The practical effect is visible with two inputs: ```vue-html <input v-if="loginType === 'email'" placeholder="Email" /> <input v-else placeholder="Username" /> ``` Type something, toggle `loginType`, and the field is **empty**: the email input was unmounted and a separate username input was mounted. Nothing is shared between branches. ## What Vue 2 did differently | | Vue 2 | Vue 3 | |---|---|---| | Same tag in two branches, no keys | element **reused**, patched in place | separate nodes, remounted | | Typed value after switching | carried over | discarded | | Keys on branches | needed to force separation | optional | | Same key on two branches | forced reuse | compile error | In Vue 2 the common advice was to add `key="email"` and `key="username"` to stop the value leaking. In Vue 3 those keys are unnecessary. If you keep manual keys, they must be different; the compiler rejects duplicates with `v-if/else branches must use unique keys.` ## If you want the value to persist Sometimes carrying the value over is the desired behaviour, for instance when only the placeholder should change. Vue 3 no longer offers the shared-key trick, so make persistence explicit: 1. Render **one** input and bind the differing attributes: `:placeholder="loginType === 'email' ? 'Email' : 'Username'"`. 2. Or keep the value in component state with `v-model`, so each newly mounted input starts from the stored value. ## Interview angles - "Why is my field empty after switching tabs?" The branches are separate nodes, so their DOM state does not carry over. - "Do I still need `key` on `v-if` branches?" No; if you add them, they must be unique. - "Can `v-else` follow a `v-show`?" No: `v-else` pairs only with `v-if` and `v-else-if`. - "Why won't my `v-else` compile?" Usually another element sits between it and the `v-if`.
- In Vue 3, how do you keep the typed text when switching between the email and username modes of a login field?Render a single `<input>` and bind only what differs, such as `:placeholder`, or store the value with `v-model` in component state so whichever input mounts starts from it. The Vue 2 trick of giving both branches the same key is a compile error in Vue 3.
- Why does a Vue 3 `v-else` placed after a `<div>` that follows the `v-if` fail?`v-else` and `v-else-if` must immediately follow a `v-if` or `v-else-if` sibling. Only whitespace and comments may sit between them; any other element breaks the chain and the compiler reports that the `v-else` has no adjacent `v-if`.
saying these in an interview costs you the question
- Vue 3 reuses same-tag elements across v-if and v-else branches.
- You must add keys to v-if branches in Vue 3.
- Giving two branches the same key forces reuse in Vue 3.
- v-else can be separated from v-if by any element.