Khởi tạo instance Vue
Tạo một instance Vue bằng cách sử dụng new Vue(), truyền vào một đối tượng cấu hình chứa các thuộc tính như el và data.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="app">
{{ greeting }}
</div>
<script>
const appInstance = new Vue({
el: '#app',
data: {
greeting: 'Xin chào!'
}
});
</script>
</body>
</html>
Liên kết dữ liệu với v-bind và v-model
Sử dụng v-bind để liên kết một chiều từ dữ liệu tới phần tử giao diện, và v-model để liên kết hai chiều giữa dữ liệu và phần tử nhập liệu.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="input-demo">
<input type="text" v-bind:value="text">
<input type="text" v-model="text">
</div>
<script>
new Vue({
el: "#input-demo",
data: {
text: 'Giá trị mặc định'
}
});
</script>
</body>
</html>
Sử dụng Object.defineProperty
Object.defineProperty cho phép định nghĩa getter và setter cho thuộc tính của một đối tượng, giúp theo dõi và điều khiển việc truy cập thuộc tính.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<script>
let internalValue = 25;
const userInfo = {
username: 'admin',
location: 'Hanoi'
};
Object.defineProperty(userInfo, 'age', {
get() {
console.log('Truy cập thuộc tính age');
return internalValue;
},
set(newValue) {
console.log('Thay đổi giá trị age thành:', newValue);
internalValue = newValue;
}
});
console.log(userInfo.age);
userInfo.age = 30;
console.log(internalValue);
</script>
</body>
</html>
Xử lý sự kiện bàn phím
Vue hỗ trợ nhiều alias cho các phím thông dụng và cho phép xử lý sự kiện bàn phím qua directive @keyup hoặc @keydown.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="keyboard-demo">
<input @keyup.enter="handleInput" placeholder="Nhấn Enter">
<input @keyup.space="handleInput" placeholder="Nhấn Space">
</div>
<script>
new Vue({
el: '#keyboard-demo',
methods: {
handleInput(event) {
console.log('Giá trị:', event.target.value);
console.log('Phím nhấn:', event.key);
}
}
});
</script>
</body>
</html>
Hiển thị tên đầy đủ bằng ba phương pháp
Có thể hiển thị tên đầy đủ bằng interpolation, phương thức trong methods, hoặc sử dụng computed properties.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="fullname-demo">
Họ: <input v-model="firstName"><br>
Tên: <input v-model="lastName"><br>
Interpolation: {{ firstName }} {{ lastName }}<br>
Methods: {{ getFullName() }}<br>
Computed: {{ fullName }}
</div>
<script>
new Vue({
el: '#fullname-demo',
data: {
firstName: 'Nguyen',
lastName: 'Van A'
},
methods: {
getFullName() {
return this.firstName + ' ' + this.lastName;
}
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}
});
</script>
</body>
</html>
Ví dụ về thời tiết
Chuyển đổi trạng thái nhiệt độ khi người dùng nhấn nút.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="weather-demo">
<h2>Nhiệt độ hôm nay: {{ temperature }}</h2>
<button @click="toggleTemp">Chuyển đổi</button>
</div>
<script>
new Vue({
el: '#weather-demo',
data: {
isHot: true
},
computed: {
temperature() {
return this.isHot ? 'Cao' : 'Thấp';
}
},
methods: {
toggleTemp() {
this.isHot = !this.isHot;
}
}
});
</script>
</body>
</html>
Duyệt danh sách với v-for
Sử dụng v-for để lặp qua mảng, đối tượng, chuỗi ký tự hoặc số lần nhất định.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="list-demo">
<ul>
<li v-for="(person, index) in people" :key="index">
{{ person.name }} - {{ person.age }}
</li>
</ul>
</div>
<script>
new Vue({
el: '#list-demo',
data: {
people: [
{ name: 'An', age: 20 },
{ name: 'Binh', age: 25 }
]
}
});
</script>
</body>
</html>
Thêm phần tử vào danh sách
<template>
<div>
<button @click="addItem">Thêm mục</button>
<p v-for="(item, idx) in items" :key="idx">{{ idx + 1 }}. {{ item }}</p>
</div>
</template>
<script>
export default {
data() {
return {
items: ['Mục 1', 'Mục 2']
};
},
methods: {
addItem() {
this.items = [...this.items, 'Mục mới'];
}
}
};
</script>
Quản lý sinh viên
<template>
<div>
<input v-model="newStudent.name" placeholder="Tên">
<button @click="addStudent">Thêm</button>
<table>
<tr v-for="(student, index) in students" :key="index">
<td>{{ student.name }}</td>
<td><button @click="removeStudent(index)">Xóa</button></td>
</tr>
</table>
</div>
</template>
<script>
export default {
data() {
return {
students: [{ name: 'Nguyen Van A' }],
newStudent: { name: '' }
};
},
methods: {
addStudent() {
if (!this.newStudent.name) {
alert('Vui lòng nhập tên!');
return;
}
this.students.push({ ...this.newStudent });
this.newStudent.name = '';
},
removeStudent(index) {
this.students.splice(index, 1);
}
}
};
</script>
Điều kiện hiển thị với v-show và v-if
v-show thay đổi thuộc tính CSS display, còn v-if thêm/xóa phần tử khỏi DOM.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="conditional-demo">
<button @click="isVisible = !isVisible">Chuyển đổi</button>
<img v-show="isVisible" src="image1.jpg">
<img v-if="!isVisible" src="image2.jpg">
</div>
<script>
new Vue({
el: '#conditional-demo',
data: {
isVisible: true
}
});
</script>
</body>
</html>
Thu thập dữ liệu biểu mẫu
Sử dụng v-model để thu thập dữ liệu từ các trường nhập liệu khác nhau.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="form-demo">
<form @submit.prevent="handleSubmit">
<input v-model="formData.username" placeholder="Tên đăng nhập"><br>
<input type="radio" v-model="formData.gender" value="Nam"> Nam
<input type="radio" v-model="formData.gender" value="Nữ"> Nữ<br>
<input type="checkbox" v-model="formData.hobbies" value="Đọc sách"> Đọc sách
<input type="checkbox" v-model="formData.hobbies" value="Du lịch"> Du lịch<br>
<select v-model="formData.city">
<option value="HN">Hà Nội</option>
<option value="HCM">TP.HCM</option>
</select><br>
<button type="submit">Gửi</button>
</form>
</div>
<script>
new Vue({
el: '#form-demo',
data: {
formData: {
username: '',
gender: '',
hobbies: [],
city: ''
}
},
methods: {
handleSubmit() {
console.log(this.formData);
}
}
});
</script>
</body>
</html>
Gán kiểu dáng động
Vue cho phép gán class và style động thông qua object hoặc array binding.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
<style>
.highlight { background: yellow; }
.large { font-size: 20px; }
</style>
</head>
<body>
<div id="styling-demo">
<div :class="{ highlight: isHighlighted, large: isLarge }">
Văn bản có kiểu dáng động
</div>
<button @click="toggleStyle">Chuyển đổi kiểu dáng</button>
</div>
<script>
new Vue({
el: '#styling-demo',
data: {
isHighlighted: true,
isLarge: false
},
methods: {
toggleStyle() {
this.isHighlighted = !this.isHighlighted;
this.isLarge = !this.isLarge;
}
}
});
</script>
</body>
</html>
Bộ lọc (Filters)
Bộ lọc dùng để định dạng dữ liệu trước khi hiển thị.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="filter-demo">
{{ price | currency }}
</div>
<script>
Vue.filter('currency', function(value) {
return new Intl.NumberFormat('vi-VN', { style: 'currency', currency: 'VND' }).format(value);
});
new Vue({
el: '#filter-demo',
data: {
price: 1234567
}
});
</script>
</body>
</html>
Directive tích hợp sẵn
- v-text: Hiển thị văn bản thuần túy, thay thế toàn bộ nội dung.
- v-html: Hiển thị HTML, cần thận trọng với XSS.
- v-cloak: Ẩn phần tử cho đến khi Vue hoàn tất biên dịch.
- v-once: Chỉ render một lần, bỏ qua cập nhật sau.
- v-pre: Bỏ qua biên dịch cho phần tử này.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
<style>
[v-cloak] { display: none; }
</style>
</head>
<body>
<div id="directive-demo" v-cloak>
<span v-text="message"></span>
<span v-html="htmlContent"></span>
<span v-once>{{ staticText }}</span>
</div>
<script>
new Vue({
el: '#directive-demo',
data: {
message: 'Văn bản đơn giản',
htmlContent: '<b>Văn bản HTML</b>',
staticText: 'Không thay đổi'
}
});
</script>
</body>
</html>
Directive tùy chỉnh
Tạo directive riêng để mở rộng chức năng.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="custom-directive-demo">
<span v-focus>Tự động focus</span>
</div>
<script>
Vue.directive('focus', {
inserted(el) {
el.focus();
}
});
new Vue({
el: '#custom-directive-demo'
});
</script>
</body>
</html>
Component không phải file đơn
Định nghĩa component bằng Vue.extend() hoặc object shorthand, sau đó đăng ký cục bộ hoặc toàn cục.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="component-demo">
<my-component></my-component>
</div>
<script>
const MyComponent = {
template: `<div>Đây là component tùy chỉnh</div>`
};
new Vue({
el: '#component-demo',
components: {
'my-component': MyComponent
}
});
</script>
</body>
</html>
Vòng đời của component (Lifecycle Hooks)
Các hàm hook như mounted, created cho phép thực thi mã ở các giai đoạn khác nhau của vòng đời component.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="vue.js"></script>
</head>
<body>
<div id="lifecycle-demo">
<h2 :style="{ opacity: opacityValue }">Chữ mờ dần</h2>
</div>
<script>
new Vue({
el: '#lifecycle-demo',
data: {
opacityValue: 1
},
mounted() {
setInterval(() => {
this.opacityValue -= 0.02;
if (this.opacityValue <= 0) this.opacityValue = 1;
}, 50);
}
});
</script>
</body>
</html>