Vue 2.x: Directives, Filters, Watchers, and Computed Properties
What is Vue?
Vue is a framework for building user interfaces. It simplifies populating HTML pages with data. As a framework, it provides a set of rules developers folllow to implement business logic. Mastering Vue requires learning its directives, components (for UI reuse), routing, Vuex, and component libraries—these are essential for Vue project development.
Two Core Features of Vue
- Data-Driven View: Data changes automatically update the view. Developers focus on data, and Vue handles rendering.
- Two-Way Data Binding: Form input (collected by Vue) and JavaScript data stay in sync. The MVVM pattern (Model, View, ViewModel) powers this.
Basic Vue Usage
- Import
vue.js. - Declare a Vue-controlled DOM area.
- Create a Vue instance (ViewModel).
<body>
<div id="app">{{ username }}</div>
<script src="./lib/vue-2.6.12.js"></script>
<script>
const app = new Vue({
el: '#app',
data: { username: 'zhangsan' },
methods: { doAction() {} }
});
</script>
</body>
Vue Directives (Template Syntax)
1. Content Rendering
v-text: Overwrites content (rarely used).- Interpolation
{{ }}: Reusable, no content overwrite. v-html: Renders HTML from strings.
<div v-text="info"></div>
<div>{{ info }}</div>
<div v-html="info"></div>
Supports simple JavaScript expressions (e.g., {{ num + 1 }}).
2. Attribute Binding
Interpolation can’t be used in attributes. Use v-bind: (shorthand :) for dynamic attributes. For string concatenation, use single quotes:
<div :title="'box' + index">A div</div>
3. Event Binding
v-on:(shorthand@).- No parameters:
<button @click="increment"></button> methods: { increment() { this.count += 1; } } - With parameters:
<button @click="increment(2)"></button> methods: { increment(n) { this.count += n; } } $eventfor event object:<button @click="increment(3, $event)"></button> methods: { increment(n, e) { this.count += 1; } }- Evant modifiers:
.prevent(stop default),.stop(stop bubbling),.capture/.once/.self(rare).
- No parameters:
4. v-model (Two-Way Binding)
Used in input (radio/checkbox), textarea, and select. Vue provides modifiers for input handling.
5. Conditional Rendering
v-show: Togglesdisplay: none(fast for frequent changes).v-if: Creates/destroys elements (better for rare changes).v-else-if/v-else: Conditional chains.
<p v-if="isActive">Active</p>
<p v-else-if="isPending">Pending</p>
<p v-else>Inactive</p>
6. List Rendering (v-for)
Renders arrays. Syntax: (item, index) in items. Use :key (unique) for performance:
<ul>
<li v-for="(item, idx) in list" :key="item.id">{{ item.name }} ({{ idx }})</li>
</ul>
Filters (Vue 2.x Only)
Removed in Vue 3.x. In 2.x, filters format data. Define in filters (private) or globally.
- Private Filter: Defined in a Vue instance’s
filtersnode. - Global Filter: Shared across instances.
Watchers
Watchers monitor data changes.
- Method Syntax: Limited (no auto-trigger, no deep watch).
- Object Syntax:
immediate: Auto-trigger the watcher.deep: Watch nested properties.
Example (immediate):
watch: {
username: {
handler(newVal, oldVal) { /* logic */ },
immediate: true
}
}
Example (deep):
watch: {
user: {
handler(newVal) { /* logic */ },
deep: true
}
}
Computed Properties
Reactive, derived data. Defined as methods, used as properties.
Example:
<div :style="{ backgroundColor: rgbColor }">{{ rgbColor }}</div>
computed: {
rgbColor() {
return `rgb(${this.r}, ${this.g}, ${this.b})`;
}
}
Case Study: Brand List
A Vue app to manage brands (add, delete, toggle status).
<div id="app">
<div class="card">
<div class="card-header">Add Brand</div>
<div class="card-body">
<form @submit.prevent="addBrand">
<input v-model.trim="brandName" placeholder="Brand Name">
<button type="submit">Add</button>
</form>
</div>
</div>
<table>
<tr v-for="item in brandList" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>
<input type="checkbox" v-model="item.active" :id="'cb' + item.id">
<label :for="'cb' + item.id" v-if="item.active">Active</label>
<label :for="'cb' + item.id" v-else>Inactive</label>
</td>
<td>{{ item.timestamp }}</td>
<td><a @click="removeBrand(item.id)">Delete</a></td>
</tr>
</table>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
brandName: '',
nextId: 4,
brandList: [
{ id: 1, name: 'BMW', active: true, timestamp: new Date() },
{ id: 2, name: 'Mercedes', active: false, timestamp: new Date() },
{ id: 3, name: 'Audi', active: true, timestamp: new Date() }
]
},
methods: {
addBrand() {
if (!this.brandName) return alert('Enter a brand!');
this.brandList.push({
id: this.nextId++,
name: this.brandName,
active: true,
timestamp: new Date()
});
this.brandName = '';
},
removeBrand(id) {
this.brandList = this.brandList.filter(i => i.id !== id);
}
}
});
</script>