Giới thiệu Vue Directives và cách tạo Custom Directives
Cập nhật gần nhất: 10/06/2024
Hello các bạn đến với trang blog của mình 👋👋
Ở bài đầu tiên trên kênh blog của mình chúng ta sẽ cùng nhau tìm hiểu các viết custom Directive trong Vue như thế nào nhé 🚀🚀
Setup
Trước khi bắt đầu bài này thì các bạn cần phải setup sẵn project VueJS trước nhé. Có thể dùng Vite, hoặc Laravel + Vite, tuỳ các bạn nha 😁
Viết Custom Directive trong VueJS
Giới thiệu
Custom Directives là một tính năng mạnh mẽ của VueJS cho phép bạn tùy chỉnh và mở rộng khả năng của HTML elements. Bằng cách tạo ra các directive của riêng bạn, bạn có thể thêm logic tùy chỉnh vào bất kỳ phần tử nào trong ứng dụng VueJS của mình. Trong bài viết này, chúng ta sẽ khám phá cách viết custom directives từ cơ bản đến nâng cao, với các ví dụ cụ thể và dễ hiểu.
Tạo Custom Directive Cơ Bản
Để bắt đầu, hãy xem cách tạo một custom directive cơ bản. Ví dụ, chúng ta sẽ tạo một directive để thay đổi màu nền của phần tử.
Local Directive
Bạn có thể tạo directive ở cấp độ component để sử dụng chỉ trong component đó.
<template>
<div>
<h1 v-bg-color="'yellow'">This background is yellow!</h1>
</div>
</template>
<script setup>
const vBgColor = {
beforeMount(el, binding) {
el.style.backgroundColor = binding.value;
}
};
</script>
Ở đây có điều đặc biệt là Vue sẽ tự động duyệt tất cả các biến mà ta khai báo trong script setup
, nếu biến nào mà có dạng camelCase
và bắt đầu bằng chữ v
thì nó sẽ "cân nhắc" có thể đó là directive
Vue thông minh phết nhờ 😍😍
Khi chạy lên ta có kết quả như sau:
Global Directive
Bạn cũng có thể register directive ở cấp độ global để sử dụng trong toàn bộ ứng dụng.
Đầu tiên ở file app.js
ta tạo directive và register global:
import './bootstrap';
import { createApp } from 'vue';
import ExampleComponent from './components/ExampleComponent.vue';
const app = createApp(ExampleComponent);
const bgColorDirective = {
beforeMount(el, binding) {
el.style.backgroundColor = binding.value;
}
};
app.directive('bg-color', bgColorDirective);
app.mount('#app');
<template>
<div>
<h1 v-bg-color="'red'">This background is yellow!</h1>
</div>
</template>
<script setup>
</script>
Chạy lên vẫn sẽ cho ta kết quả tương tự:
Và bởi vì đây là global directive nên nó có thể được sử dụng ở mọi component
Các Hook của Directive
VueJS cung cấp nhiều hook khác nhau cho custom directive:
created
: Gọi trước khi element attribute hay event listener được khởi tạo nhưng trước khi các phần tử con được gắn vào DOMbeforeMount
: Gọi ngay trước khi phần tử được gắn vào DOM.mounted
: Gọi sau khi phần tử được gắn vào DOM.beforeUpdate
: Gọi ngay trước khi phần tử được cập nhật (VD: khi dữ liệu thay đổi).updated
: Gọi sau khi phần tử và con của nó được cập nhật.beforeUnmount
: Gọi ngay trước khi phần tử được gỡ bỏ khỏi DOM.unmounted
: Gọi sau khi phần tử được gỡ bỏ khỏi DOM.
Ví dụ với Các Hook
Ta cùng xem ví dụ với tất cả các hook nhé:
<template>
<div>
<h1 v-custom="message">Hover over me!</h1>
</div>
</template>
<script setup>
import { ref } from 'vue';
const message = ref('Hello, World!');
const vCustom = {
created(el, binding) {
console.log('created', binding.value);
},
beforeMount(el, binding) {
console.log('beforeMount', binding.value);
},
mounted(el, binding) {
el.addEventListener('mouseover', () => {
el.style.color = 'red';
});
el.addEventListener('mouseleave', () => {
el.style.color = 'black';
});
console.log('mounted', binding.value);
},
beforeUpdate(el, binding) {
console.log('beforeUpdate', binding.value);
},
updated(el, binding) {
console.log('updated', binding.value);
},
beforeUnmount(el, binding) {
console.log('beforeUnmount', binding.value);
},
unmounted(el, binding) {
console.log('unmounted', binding.value);
}
};
</script>
Object Literal
Bạn có thể truyền một object làm giá trị cho directive:
<template>
<div>
<h1 v-style="{ color: textColor, backgroundColor: bgColor }">Styled Text</h1>
</div>
</template>
<script setup>
import { ref } from 'vue';
const textColor = ref('white');
const bgColor = ref('blue');
const vStyle = {
beforeMount(el, binding) {
Object.keys(binding.value).forEach(key => {
el.style[key] = binding.value[key];
});
}
};
</script>
Chạy lên ta sẽ thấy như sau:
Vọc vạch
Directive với animation khi hover
Ta sẽ tạo một directive để thêm animation khi hover vào phần tử nhé:
<template>
<div class="container">
<h1 v-hover-animate>Hover over me for animation!</h1>
</div>
</template>
<script setup>
const vHoverAnimate = {
beforeMount(el) {
el.style.transition = 'transform 0.3s';
},
mounted(el) {
el.addEventListener('mouseover', () => {
el.style.transform = 'scale(1.2)';
});
el.addEventListener('mouseleave', () => {
el.style.transform = 'scale(1)';
});
}
};
</script>
<style>
.container {
max-width: 1320px;
}
</style>
Ở trên các bạn thấy rằng mỗi khi ta lia chuột vào dòng text thì nó sẽ được scale lên, và scale xuống khi ta lia ra ngoài
cool phết nhờ 😎
Tương tác với bàn phím
Tiếp tục ta tạo một directive để thêm tương tác với bàn phím nha:
<template>
<div class="container">
<input v-keyboard-interactive />
</div>
</template>
<script setup>
const vKeyboardInteractive = {
mounted(el) {
el.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
el.style.backgroundColor = 'lightgreen';
} else {
el.style.backgroundColor = 'lightcoral';
}
});
}
};
</script>
<style>
.container {
max-width: 1320px;
}
</style>
Ở đây mỗi khi ta gõ 1 phím bất kì thì màu ô input sẽ đổi thành màu đỏ, trừ phím Enter sẽ đổi thành màu xanh
Các Vấn Đề Xung Quanh
Khi Nào Nên Dùng Custom Directive?
Custom directives nên được sử dụng khi bạn cần thao tác trực tiếp với DOM. Tuy nhiên, hãy hạn chế sử dụng nếu có thể giải quyết bằng component hoặc phương thức khác của VueJS.
Performance và Maintainability
Tránh lạm dụng custom directives vì có thể ảnh hưởng đến hiệu suất và độ bảo trì của ứng dụng. Hãy chắc chắn rằng directive của bạn thực sự cần thiết và không thể thay thế bằng cách khác.
Kết bài
Custom directives trong VueJS là một công cụ mạnh mẽ cho phép bạn mở rộng khả năng của HTML elements. Từ các ví dụ cơ bản đến nâng cao, hy vọng bạn đã hiểu cách tạo và sử dụng custom directives một cách hiệu quả. Hãy thử nghiệm và áp dụng vào dự án của bạn để khám phá hết tiềm năng của VueJS!
All rights reserved