Appearance
Custom Directives
Giới Thiệu
Ngoài bộ các chỉ thị mặc định được gửi kèm trong core (như v-model
hoặc v-show
), Vue cũng cho phép bạn đăng ký các chỉ thị tùy chỉnh của riêng bạn.
Chúng tôi đã giới thiệu hai hình thức tái sử dụng mã trong Vue: components và composables. Components là các khối xây dựng chính, trong khi composables tập trung vào việc tái sử dụng logic có trạng thái. Ngược lại, các chỉ thị tùy chỉnh chủ yếu được thiết kế để tái sử dụng logic liên quan đến việc truy cập DOM cấp thấp trên các phần tử đơn giản.
Một chỉ thị tùy chỉnh được định nghĩa như một đối tượng chứa các hooks vòng đời tương tự như của một component. Các hooks nhận phần tử mà chỉ thị được ràng buộc. Dưới đây là một ví dụ về một chỉ thị đặc biệt để tập trung vào một ô nhập khi phần tử được chèn vào DOM bởi Vue:
vue
<script setup>
// kích hoạt v-focus trong các mẫu
const vFocus = {
mounted: (el) => el.focus()
}
</script>
<template>
<input v-focus />
</template>
Giả sử bạn chưa nhấp chuột nơi nào khác trên trang, ô nhập ở trên nên được tập trung tự động. Chỉ thị này hữu ích hơn so với thuộc tính autofocus
vì nó không chỉ hoạt động khi trang được tải - nó cũng hoạt động khi phần tử được chèn động bởi Vue.
Trong <script setup>
, bất kỳ biến nào viết liền bắt đầu bằng tiền tố v
có thể được sử dụng như một chỉ thị tùy chỉnh. Trong ví dụ trên, vFocus
có thể được sử dụng trong mẫu như v-focus
.
Nếu không sử dụng <script setup>
, chỉ thị tùy chỉnh có thể được đăng ký bằng cách sử dụng tùy chọn directives
:
js
export default {
setup() {
/*...*/
},
directives: {
// kích hoạt v-focus trong mẫu
focus: {
/* ... */
}
}
}
Thường thấy cũng là việc đăng ký các chỉ thị tùy chỉnh toàn cầu tại cấp ứng dụng:
js
const app = createApp({})
// làm cho v-focus có thể được sử dụng trong tất cả các component
app.directive('focus', {
/* ... */
})
TIP
Chỉ nên sử dụng chỉ thị tùy chỉnh khi chức năng mong muốn chỉ có thể đạt được thông qua quản lý DOM trực tiếp. Ưu tiên sử dụng templating mô tả bằng các chỉ thị tích hợp sẵn như v-bind
khi có thể vì chúng hiệu quả hơn và thân thiện với việc render trên máy chủ.
Các Hook của Chỉ Thị
Một đối tượng định nghĩa chỉ thị có thể cung cấp một số hàm hook (tất cả đều tùy chọn):
js
const myDirective = {
// được gọi trước khi các thuộc tính của phần tử được ràng buộc
// hoặc các lắng nghe sự kiện được áp dụng
created(el, binding, vnode, prevVnode) {
// xem bên dưới để biết chi tiết về các đối số
},
// được gọi ngay trước khi phần tử được chèn vào DOM.
beforeMount(el, binding, vnode, prevVnode) {},
// được gọi khi phần tử ràng buộc của nó
// và tất cả các con của nó được chèn.
mounted(el, binding, vnode, prevVnode) {},
// được gọi trước khi phần tử ràng buộc của nó được cập nhật
beforeUpdate(el, binding, vnode, prevVnode) {},
// được gọi sau khi phần tử ràng buộc của cha
// và tất cả các con của nó đã được cập nhật
updated(el, binding, vnode, prevVnode) {},
// được gọi trước khi phần tử ràng buộc của cha bị giải ràng buộc
beforeUnmount(el, binding, vnode, prevVnode) {},
// được gọi khi phần tử ràng buộc của cha bị giải ràng buộc
unmounted(el, binding, vnode, prevVnode) {}
}
Đối số của Hook
Các hook của chỉ thị nhận các đối số sau:
el
: phần tử mà chỉ thị được ràng buộc. Điều này có thể được sử dụng để trực tiếp thao tác DOM.binding
: một đối tượng chứa các thuộc tính sau.value
: Giá trị được chuyển cho chỉ thị. Ví dụ, trongv-my-directive="1 + 1"
, giá trị sẽ là2
.oldValue
: Giá trị trước đó, chỉ có sẵn trongbeforeUpdate
vàupdated
. Nó có sẵn dù có hay không giá trị đã thay đổi.arg
: Đối số được chuyển cho chỉ thị, nếu có. Ví dụ, trongv-my-directive:foo
, đối số sẽ là"foo"
.modifiers
: Một đối tượng chứa các modifier, nếu có. Ví dụ, trongv-my-directive.foo.bar
, đối tượng modifier sẽ là{ foo: true, bar: true }
.instance
: Thể hiện của component mà chỉ thị được sử dụng.dir
: đối tượng định nghĩa chỉ thị.
vnode
: VNode cơ bản đại diện cho phần tử được ràng buộc.prevNode
: VNode đại diện cho phần tử được ràng buộc từ lần render trước. Chỉ có sẵn trong các hookbeforeUpdate
vàupdated
.
Như một ví dụ, xem xét việc sử dụng chỉ thị sau:
template
<div v-example:foo.bar="baz">
Đối số binding
sẽ là một đối tượng như sau:
js
{
arg: 'foo',
modifiers: { bar: true },
value: /* giá trị của `baz` */,
oldValue: /* giá trị của `baz` từ cập nhật trước đó */
}
Tương tự như các chỉ thị tích hợp sẵn, các đối số của chỉ thị tùy chỉnh có thể là động. Ví dụ:
template
<div v-example:[arg]="value"></div>
Ở đây, đối số của chỉ thị sẽ được cập nhật một cách phản ứng dựa trên thuộc tính arg
trong trạng thái của component chúng ta.
Ghi chú
Ngoại trừ el
, bạn nên coi những đối số này như chỉ có thể đọc và không bao giờ được sửa đổi. Nếu bạn cần chia sẻ thông tin giữa các hook, khuyến cáo làm điều đó thông qua dataset của phần tử.
Tự Shorthand
Thường thì một chỉ thị tùy chỉnh có thể có cùng hành vi cho cả mounted
và updated
, mà không cần các hook khác. Trong những trường hợp như vậy, chúng ta có thể định nghĩa chỉ thị dưới dạng một hàm:
template
<div v-color="color"></div>
js
app.directive('color', (el, binding) => {
// điều này sẽ được gọi cho cả `mounted` và `updated`
el.style.color = binding.value
})
Đối Tượng Chữ Nhật
Nếu chỉ thị của bạn cần nhiều giá trị, bạn cũng có thể truyền vào một đối tượng chữ nhật JavaScript. Hãy nhớ rằng chỉ thị có thể nhận bất kỳ biểu thức JavaScript hợp lệ nào.
template
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
js
app.directive('demo', (el, binding) => {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})
Sử Dụng Trên Các Component
Khi sử dụng trên các component, chỉ thị tùy chỉnh sẽ luôn áp dụng cho nút gốc của một component, tương tự như Thuộc tính chuyển tiếp.
template
<MyComponent v-demo="test" />
template
<!-- template của MyComponent -->
<div> <!-- Chỉ thị v-demo sẽ được áp dụng ở đây -->
<span>Nội dung component của tôi</span>
</div>
Lưu ý rằng các component có thể có nhiều hơn một nút gốc. Khi áp dụng cho một component có nhiều nút gốc, một chỉ thị sẽ bị bỏ qua và một cảnh báo sẽ được thông báo. Khác với thuộc tính, các chỉ thị không thể được chuyển đến một phần tử khác với v-bind="$attrs"
. Nói chung, không khuyến khích việc sử dụng chỉ thị tùy chỉnh trên các component.