+11

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:

Screenshot 2024-06-09 at 11.39.54 PM.png

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ự:

Screenshot 2024-06-09 at 11.42.27 PM.png

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 DOM
  • beforeMount: 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>

ezgif-6-0f24390908.gif

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:

Screenshot 2024-06-09 at 11.49.52 PM.png

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>

ezgif-6-a49c6db16e.gif

Ở 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>

ezgif-6-1da62ca250.gif

Ở đâ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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí