Vue docs, chapter by chapter

Essentials II — rendering, events and forms

Conditional and List Rendering, Event Handling, Form Input Bindings, Watchers, Template Refs, Components Basics and Lifecycle Hooks, as the guide states them.

These chapters are where the modifiers live: the v-on modifiers, the key and system modifiers, the v-model modifiers, the watcher options. They are exactly the kind of fact an interviewer can check in five seconds, and exactly the kind that fades if you have used a UI library for two years.

Know — Conditional and List Rendering

  • v-if / v-else-if / v-else on adjacent elements; <template v-if> groups elements without a wrapper. v-show toggles display and keeps the element; it does not work on <template> and has no v-else. v-if is lazy and has higher toggle cost; v-show has higher initial cost and cheap toggles.
  • v-if with v-for on the same element is not recommended; in Vue 3 v-if is evaluated first and cannot see the loop variable. Move v-if to a wrapping <template v-for>.
  • v-for: (item, index) in items, of works like in, objects iterate as (value, key, index) in Object.values order, and a range n in 10 starts at 1. <template v-for> renders multiple elements per item.
  • key should be a string or number, never an object; without a key Vue patches in place, which is efficient only when the list output does not depend on child component state or temporary DOM state.
  • Array change detection: mutating methods (push, pop, shift, unshift, splice, sort, reverse) trigger updates; non-mutating methods (filter, concat, slice) return a new array that you assign. reverse() and sort() mutate: copy before using them in a computed.
  • Filtered or sorted lists are computeds; inside nested v-for where a computed is not feasible, use a method.
  • Components in v-for do not receive item automatically; pass props explicitly.

Know — Event Handling

  • Inline handlers (@click="count++") and method handlers (@click="greet", which receives the native event). Call methods inline with arguments and pass $event or an arrow function for the event.
  • Event modifiers: .stop, .prevent, .self, .capture, .once, .passive. Order matters (@click.prevent.self vs @click.self.prevent); do not combine .passive with .prevent.
  • Key modifiers: .enter, .tab, .delete (Delete and Backspace), .esc, .space, .up, .down, .left, .right, plus any kebab-cased KeyboardEvent.key (.page-down). System modifiers: .ctrl, .alt, .shift, .meta; .exact requires exactly those. Mouse: .left, .right, .middle.
  • Multiple handlers on one event: @click="one($event), two($event)".

Know — Form Input Bindings

  • v-model on <input>, <textarea>, <select>, checkboxes and radios; it ignores the initial value, checked and selected attributes and uses the bound state as the source of truth. Interpolation inside <textarea> does not work; use v-model.
  • Checkbox: boolean, or an array when several share a v-model; true-value/false-value customise the values (not submitted with the form). Radio: the bound value. Select: single value or array with multiple; add a disabled empty option as placeholder to avoid the iOS first-option bug. Options can be rendered with v-for and bound to objects with :value.
  • Modifiers: .lazy (sync on change instead of input), .number (cast with parseFloat, kept as string if it fails; automatic for type="number"), .trim.
  • IME composition: v-model does not update during composition; bind :value and @input if you need it to.

Know — Watchers

  • Sources: a ref, a reactive object (implicitly deep), a getter, or an array of these. You cannot watch a property of a reactive object directly (watch(obj.count, …) passes a number); use a getter.
  • Options: deep: true (traverses; expensive), deep: number (3.5+, depth limit), immediate: true, once: true (3.4+), flush: 'pre' | 'post' | 'sync'.
  • watchEffect runs immediately and tracks whatever it reads synchronously before the first await; use watch when you need old values, laziness or control over which dependencies trigger.
  • Cleanup: onWatcherCleanup() (3.5+, must be called synchronously during the callback) or the onCleanup argument passed to the callback.
  • Timing: by default callbacks run before the owner component updates (pre); watchPostEffect/flush: 'post' run after the DOM update; watchSyncEffect/flush: 'sync' run synchronously.
  • Stopping: watchers created synchronously in setup stop with the component; watchers created asynchronously must be stopped manually with the returned handle, which in 3.5 also has pause() and resume().

Know — Template Refs, Components Basics, Lifecycle

  • ref attribute plus useTemplateRef('name') (3.5+) or a ref with the same name; available after mount, null when unmounted. Refs in v-for yield an array whose order is not guaranteed. Function refs receive the element. A ref on a component gives the instance; with <script setup> only defineExposed members are visible.
  • Components basics: import in <script setup> and use directly; props via defineProps; events via defineEmits/$emit; content via slots; dynamic components with <component :is> (string name or component object). In-DOM template caveats: case insensitivity (kebab-case names and props), no self-closing tags, and element placement restrictions (<table>) solved with is="vue:my-row".
  • Lifecycle: onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured, onRenderTracked/onRenderTriggered (dev only), onActivated/onDeactivated, onServerPrefetch. Hooks must be registered synchronously during setup; a hook registered after an await is not attached to the instance.

How it works

app/components/Docs/EssentialsTwo.vue
<script setup lang="ts">
const items = ref([{ id: 1, name: 'b', done: false }, { id: 2, name: 'a', done: true }])
const sorted = computed(() => [...items.value].sort((x, y) => x.name.localeCompare(y.name))) // copy before sort
const query = ref('')
const agree = ref<'yes' | 'no'>('no')
const input = useTemplateRef<HTMLInputElement>('input')

// Cannot watch items.length directly: use a getter. `once` since 3.4.
watch(() => items.value.length, n => console.log('count', n), { once: true })

watch(query, async (q, _old, onCleanup) => {
  const controller = new AbortController()
  onCleanup(() => controller.abort())
  await $fetch('/api/search', { query: { q }, signal: controller.signal })
})

onMounted(() => input.value?.focus())
</script>

<template>
  <input ref="input" v-model.trim.lazy="query" @keyup.enter.exact="query = ''" @keydown.ctrl.enter="console.log('save')">
  <input v-model="agree" type="checkbox" true-value="yes" false-value="no">

  <ul>
    <template v-for="item in sorted" :key="item.id">
      <li v-if="!item.done" @click.self.prevent="item.done = true">{{ item.name }}</li>
    </template>
  </ul>
  <p v-show="items.length === 0">Nothing to do</p>
</template>
Gotcha· `.passive` with `.prevent`

.passive promises the browser you will not call preventDefault(), which lets scrolling start immediately; combining it with .prevent makes the browser ignore the prevent and warn. Pick one.

Exercise

Exercise
  • Write a keyboard shortcut handler using .ctrl.enter.exact and test it with and without Shift held.
  • Bind three checkboxes to one array and a radio group to a string; log the values on change.
  • Create a watcher inside a setTimeout and confirm it keeps firing after the component unmounts; then stop it with the handle.

Be able to say

Be able to say· Which v-model and v-on modifiers exist, and when do you use them?

"v-model has .lazy to sync on change instead of input, .number to cast with parseFloat, which is automatic on number inputs, and .trim. v-on has event modifiers .stop, .prevent, .self, .capture, .once and .passive, applied in the order written; key modifiers such as .enter, .esc, .tab, .delete and any kebab-cased key name; system modifiers .ctrl, .alt, .shift, .meta with .exact to require that exact combination; and mouse modifiers .left, .right, .middle. The one combination to avoid is .passive with .prevent."

Your notes

Open in Notes

Nothing yet. Notes filed here show up on this page and the section overview.