Directives

Conditional Rendering

v-if, v-else-if, v-else: conditionally render elements.

<div v-if="score >= 90">Excellent!</div>
<div v-else-if="score >= 70">Good job!</div>
<div v-else>Keep trying!</div>

Don't combine v-if with v-for on the same element - it's rejected at compile time (reported via the onError hook and console.error, and the element is left uncompiled). Use a computed filtered list, or move v-if to a wrapping element, instead:

<!-- Don't -->
<li v-if="show" v-for="item in items">{{ item }}</li>

<!-- Do: move v-if to a real wrapping element (there's no <template> support,
     so it has to be an actual rendering element, e.g. the containing <ul>) -->
<ul v-if="show">
    <li v-for="item in items">{{ item }}</li>
</ul>

<!-- or filter the source instead of the render -->
<li v-for="item in visibleItems">{{ item }}</li>

List Rendering

v-for: repeat elements for each item in an array.

<!-- Simple iteration -->
<li v-for="item in items">{{ item }}</li>

<!-- With index -->
<li v-for="(item, index) in items">
    {{ index + 1 }}. {{ item.name }}
</li>

<!-- With key (recommended) -->
<li v-for="item in items" :key="item.id">
    {{ item.name }}
</li>

v-for behavior:

  • Object items are reactive (direct property access, and stay live when passed to a method: @click="handleItem(item)" receives the real reactive object)
  • Primitive items are ref-wrapped internally to stay live across re-renders, but you never see the box: reading them ({{ item }}), binding them (:attr="item"), and passing them to a method (@click="handleItem(item)") all hand you the raw value
  • To mutate a primitive item, write to the source array by index (items[index]++), not the loop variable itself - same as Vue, a v-for primitive item isn't its own reactive cell
  • The index is a plain number that updates correctly when the array changes
  • Always use :key with unique IDs for performance

Content Directives

<p v-text="message"></p>          <!-- Safe textContent -->
<div v-show="isVisible">...</div> <!-- Toggle display -->

v-html (raw innerHTML) is intentionally not part of the core - see Plugins.

Two-Way Binding

v-model: bind form inputs bidirectionally.

<input v-model="username" />
<textarea v-model="bio"></textarea>
<input type="checkbox" v-model="agreed" />
<input type="radio" v-model="color" value="red" />
<select v-model="country">
    <option value="us">United States</option>
</select>

Event Handling

@event or v-on:event: attach event listeners.

<!-- Method handler (recommended) -->
<button @click="handleClick">Click me</button>

<!-- Inline expression -->
<button @click="count.value++">Increment</button>
<button @click="user.name = 'Jane'">Rename</button>

On .value in inline expressions: you only need .value to reassign a primitive ref itself (count.value++, count.value = 5) - a bare number can't carry the write back to the ref. Reading or mutating the contents of a ref never needs .value, including for object refs in event handlers (user.name = 'Jane' works directly when user = ref({ name: 'John' }), since the object is shared by reference).

Event modifiers — chain one or more with dots:

<form @submit.prevent="save">...</form>          <!-- e.preventDefault() -->
<button @click.stop="onClick">...</button>       <!-- e.stopPropagation() -->
<button @click.once="init">...</button>          <!-- listener fires once -->
<div @click.self="onDivClick">...</div>          <!-- ignores bubbled child clicks -->
<button @click.capture="onClick">...</button>    <!-- listen during capture phase -->
<div @scroll.passive="onScroll">...</div>        <!-- passive listener -->

Key modifiers — any modifier that isn't one of the above is matched against e.key (case-insensitive):

<input @keyup.enter="submit" />
<input @keyup.escape="cancel" />
<div @keydown.arrowdown="moveDown"></div>

Attribute Binding

:attribute or v-bind:attribute: dynamically bind any attribute.

<img :src="imageUrl" :alt="imageAlt" />
<button :disabled="isDisabled">Submit</button>
<div :class="{ active: isActive, error: hasError }">Content</div>
<div :class="[baseClass, { active: isActive }]">Content</div>  <!-- array syntax -->
<div :style="{ color: textColor, fontSize: size + 'px' }">Text</div>

Continue with Components.

Wrium v1.0.0 · MIT License