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>
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:
@click="handleItem(item)" receives the real reactive object){{ item }}), binding them (:attr="item"), and passing them to a method (@click="handleItem(item)") all hand you the raw valueitems[index]++), not the loop variable itself - same as Vue, a v-for primitive item isn't its own reactive cell:key with unique IDs for performance<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.
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 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 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.