Directive tùy biến

Giới thiệu

Bên cạnh những directive được cung cấp mặc định (v-model và v-show), Vue cũng cho phép bạn đăng kí các directive tùy biến của riêng mình. Lưu ý là trong phiên bản Vue 2.0, cách tốt nhất để sử dụng lại và trừu tượng hóa code là dùng component, tuy nhiên có thể có những lúc bạn cần một số truy xuất cấp thấp đến các phần tử web, và trong những trường hợp này thì directive tùy biến sẽ trở nên hữu ích. Ví dụ, đây là một phần tử input được focus tự động:

Khi trang này được tải, phần tử trên đây sẽ được focus (lưu ý: tính năng focus tự động không được hỗ trợ trên mobile Safari). Nếu bạn chưa hề bấm vào bất kì đâu khác trên trang, ngay lúc này phần tử input sẽ có focus. Giờ chúng ta hãy viết directive hỗ trợ cho tính năng này:

// Đăng kí một directive tùy biến cấp toàn cục với tên là `v-focus`
Vue.directive('focus', {
// Khi phần tử liên quan được thêm vào DOM...
inserted: function (el) {
// Ta gán focus vào phần tử đó
el.focus()
}
})

Nếu muốn đăng kí directive ở cấp cục bộ thay vì toàn cục, bạn có thể dùng tùy chọn directives khi khai báo component:

directives: {
focus: {
// định nghĩa cho directive
inserted: function (el) {
el.focus()
}
}
}

Sau đó trong template, bạn có thể dùng thuộc tính v-focus trên bất kì phần tử nào, như sau:

<input v-focus>

Các hàm hook

Một object khai báo directive có thể cung cấp một số hàm hook (tất cả các hàm này đều không bắt buộc):

Chúng ta sẽ tìm hiểu về các tham số được truyền vào các hàm hook này trong phần tiếp theo.

Tham số của các hàm hook

Các hàm hook cho directive được truyền vào các tham số sau đây:

Ngoài el, bạn nên coi là read-only (chỉ đọc) và đừng bao giờ chỉnh sửa các tham số này. Nếu muốn chia sẻ thông tin giữa các hook với nhau, bạn nên dùng dataset.

Sau đây là ví dụ về một directive tùy biến với các thuộc tính này:

<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
})

new Vue({
el: '#hook-arguments-example',
data: {
message: 'Cà rốt'
}
})

Cách khai báo rút gọn

Trong nhiều trường hợp, có thể bạn muốn bind và update có chung một hành vi và không quan tâm đến các hook khác. Những lúc này bạn có thể dùng cách khai báo directive rút gọn, ví dụ:

Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})

Truyền object trực tiếp

Nếu directive của bạn cần nhiều giá trị cùng một lúc, bạn có thể trực tiếp truyền vào một object. Nhớ là directive trong Vue có thể nhận bất kì biểu thức JavaScript hợp lệ nào.

<div v-demo="{ color: 'white', text: 'Su hào' }"></div>
Vue.directive('demo', function (el, binding) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "Su hào"
})