Vue.js directives are special attributes that extend HTML with reactive behavior, allowing developers to manipulate the DOM based on data changes. They are prefixed with v- and instruct Vue to perform specific actions when applied to an element.
1. Conditional Rendering
Vue offers directives to control the presence or visibility of elements based on conditions.
v-if
The v-if directive conditionally renders a block. The element and its contents are only rendered if the directive's expression evaluates to a truthy value. If false, the element is entirely removed from the DOM.
<p v-if="displayMessage">This message is visible.</p>
Here, displayMessage is a data property (e.g., true or false). The paragraph will appear only when displayMessage is true.
You can also chain v-if with v-else and v-else-if to create conditional blocks.
<div v-if="currentWeather === 'sunny'">
It's a bright day!
</div>
<div v-else-if="currentWeather === 'rainy'">
Don't forget your umbrella.
</div>
<div v-else>
Uncertain weather ahead.
</div>
v-show
Another option for conditional display is the v-show directive. It operates similarly to v-if in terms of effect but differs in its implementation.
<p v-show="isBannerVisible">Welcome to our site!</p>
When isBannerVisible is false, the element will still be rendered in the DOM, but its CSS display property will be set to none. v-show does not support v-else.
v-if vs. v-show
v-ifperforms "real" conditional rendering. It ensures that event listeners and child components within the conditional block are properly destroyed and recreated during toggling.v-ifis also lazy; if the condition is false on initial render, nothing is rendered until the condition first becomes true.v-showis simpler: the element is always rendered, and its visibility is toggled by CSSdisplayproperty.
Generally, v-if has higher toggle costs, while v-show has higher initial render costs. Use v-show for frequent toggling, and v-if for conditions that rarely change at runtime.
v-if with v-for
When v-if and v-for are used on the same element, v-for takes precedence. This means the v-if will be evaluated for each iteration of the loop.
2. Class and Style Binding
Managing an element's class list and inline styles is a common requirement in dynamic UIs. The v-bind directive handles these situations efficiently. While v-bind can accept a string, Vue enhances its capabilities for class and style attributes to also accept objects or arrays.
v-bind can be shortened to a colon (:).
String Binding
For simple attribute binding, v-bind can directly take a string expression.
<span :title="hoverInfo">Hover over me for details</span>
data: {
hoverInfo: `Page loaded at ${new Date().toLocaleTimeString()}`
}
When a user hovers over the <span>, the hoverInfo value will be displayed as a tooltip.
Binding HTML Classes
Object Syntax
You can pass an object to :class to dynamically toggle classes. The class will be applied if its corresponding boolean value is true.
<div :class="{ 'active-state': isActive, 'error-alert': hasError }"></div>
<button @click="toggleActive">Toggle Active</button>
data: {
isActive: true,
hasError: false
},
methods: {
toggleActive() {
this.isActive = !this.isActive;
}
}
This div will have the active-state class when isActive is true. Multiple classes can be appplied simultaneously, and :class can coexist with a plain class attribute.
Array Syntax
An array can be passed to :class to apply a list of classes.
<div :class="[primaryStyle, statusClass]"></div>
data: {
primaryStyle: 'main-layout',
statusClass: 'text-success'
}
This would render as <div class="main-layout text-success"></div>.
Conditional classes within an array can be achieved using the ternary operator:
<div :class="[isFocused ? 'focus-border' : '', 'base-padding']"></div>
For more complex conditions, you can embed object syntax within the array:
<div :class="[{ selected-item: isSelected }, 'border-lg']"></div>
3. Event Handling
The v-on directive allows you to listen for DOM events and execute JavaScript when they are triggered. v-on can be shortened to an at symbol (@).
Listening to Events
<div id="app">
<button @click="clickCount++">Clicked {{ clickCount }} times</button>
<p>Total clicks: {{ clickCount }}</p>
</div>
new Vue({
el: '#app',
data: {
clickCount: 0
}
});
Each click on the button increments clickCount, which is reflected in both the button text and the paragraph.
Event Handling Methods
For more complex logic, v-on can accept the name of a method to call when the event occurs.
<div id="app">
<button @click="handleButtonClick">Increment: {{ counter }}</button>
<p>Current value: {{ counter }}</p>
</div>
new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
handleButtonClick() {
this.counter++;
}
}
});
This approach centralizes event logic within the component's methods option, promoting cleaner separation of concerns.
Placing event listeners directly in the HTML template with v-on offers several advantages:
- Readability: Quickly identify event handlers and their corresponding methods by scanning the template.
- Decoupling: ViewModel logic remains pure and decoupled from the DOM, simplifying testing.
- Automatic Cleanup: Event handlers are automatically removed when a component is destroyed, preventing memory leaks.
4. List Rendering
The v-for directive is used to render a list of items based on an array or an object.
Iterating an Array
v-for requires a special syntax: item in items, where items is the source array and item is an alias for the current array element being iterated. v-for also supports an optional second argument for the current item's index.
<ul id="task-list">
<li v-for="(task, index) in tasks" :key="task.id">
{{ index + 1 }}. {{ task.description }}
</li>
</ul>
new Vue({
el: '#task-list',
data: {
tasks: [
{ id: 1, description: 'Learn Vue Directives' },
{ id: 2, description: 'Build a Vue Component' },
{ id: 3, description: 'Deploy Vue Application' }
]
}
});
Iterating an Object
You can also use v-for to iterate over an object's properties. The syntax supports (value, key, index) in object.
<div id="user-profile">
<h3>User Details</h3>
<ul>
<li v-for="(propValue, propName, index) in user" :key="propName">
{{ index + 1 }}. {{ propName }}: {{ propValue }}
</li>
</ul>
</div>
new Vue({
el: '#user-profile',
data: {
user: {
firstName: 'Jane',
lastName: 'Doe',
age: 30,
occupation: 'Developer'
}
}
});