## 簡介
除了核心功能默認內置的指令 (`v-model` 和 `v-show`),Vue 也允許注冊自定義指令。注意,在 Vue2.0 中,代碼復用和抽象的主要形式是組件。然而,有的情況下,你仍然需要對普通 DOM 元素進行底層操作,這時候就會用到自定義指令。舉個聚焦輸入框的例子,如下:
當頁面加載時,該元素將獲得焦點 (注意:`autofocus` 在移動版 Safari 上不工作)。事實上,只要你在打開這個頁面后還沒點擊過任何內容,這個輸入框就應當還是處于聚焦狀態。現在讓我們用指令來實現這個功能:
``` js
// 注冊一個全局自定義指令 `v-focus`
Vue.directive('focus', {
// 當被綁定的元素插入到 DOM 中時……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
```
如果想注冊局部指令,組件中也接受一個 `directives` 的選項:
``` js
directives: {
focus: {
// 指令的定義
inserted: function (el) {
el.focus()
}
}
}
```
然后你可以在模板中任何元素上使用新的 `v-focus` 屬性,如下:
``` html
<input v-focus>
```
## 鉤子函數
一個指令定義對象可以提供如下幾個鉤子函數 (均為可選):
- `bind`:只調用一次,指令第一次綁定到元素時調用。在這里可以進行一次性的初始化設置。
- `inserted`:被綁定元素插入父節點時調用 (僅保證父節點存在,但不一定已被插入文檔中)。
- `update`:所在組件的 VNode 更新時調用,**但是可能發生在其子 VNode 更新之前**。指令的值可能發生了改變,也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板更新 (詳細的鉤子函數參數見下)。
- `componentUpdated`:指令所在組件的 VNode **及其子 VNode** 全部更新后調用。
- `unbind`:只調用一次,指令與元素解綁時調用。
接下來我們來看一下鉤子函數的參數 (即 `el`、`binding`、`vnode` 和 `oldVnode`)。
## 鉤子函數參數
指令鉤子函數會被傳入以下參數:
- `el`:指令所綁定的元素,可以用來直接操作 DOM 。
- `binding`:一個對象,包含以下屬性:
- `name`:指令名,不包括 `v-` 前綴。
- `value`:指令的綁定值,例如:`v-my-directive="1 + 1"` 中,綁定值為 `2`。
- `oldValue`:指令綁定的前一個值,僅在 `update` 和 `componentUpdated` 鉤子中可用。無論值是否改變都可用。
- `expression`:字符串形式的指令表達式。例如 `v-my-directive="1 + 1"` 中,表達式為 `"1 + 1"`。
- `arg`:傳給指令的參數,可選。例如 `v-my-directive:foo` 中,參數為 `"foo"`。
- `modifiers`:一個包含修飾符的對象。例如:`v-my-directive.foo.bar` 中,修飾符對象為 `{ foo: true, bar: true }`。
- `vnode`:Vue 編譯生成的虛擬節點。移步 [VNode API](../api/#VNode-接口) 來了解更多詳情。
- `oldVnode`:上一個虛擬節點,僅在 `update` 和 `componentUpdated` 鉤子中可用。
<p class="tip">除了 `el` 之外,其它參數都應該是只讀的,切勿進行修改。如果需要在鉤子之間共享數據,建議通過元素的 [`dataset`](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/dataset) 來進行。</p>
這是一個使用了這些屬性的自定義鉤子樣例:
``` html
<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
```
``` js
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: 'hello!'
}
})
```
## 函數簡寫
在很多時候,你可能想在 `bind` 和 `update` 時觸發相同行為,而不關心其它的鉤子。比如這樣寫:
``` js
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
```
## 對象字面量
如果指令需要多個值,可以傳入一個 JavaScript 對象字面量。記住,指令函數能夠接受所有合法的 JavaScript 表達式。
``` html
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
```
``` js
Vue.directive('demo', function (el, binding) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})
```
- 寫在前面
- 基礎
- 安裝
- 介紹
- Vue實例
- 模板語法
- 計算屬性和偵聽器
- Class 與 Style 綁定
- 條件渲染
- 列表渲染
- 事件處理
- 表單輸入綁定
- 組件基礎
- 深入了解組件
- 組件注冊
- Prop
- 自定義事件
- 插槽
- 動態組件 & 異步組件
- 處理邊界情況
- 過渡 & 動畫
- 進入/離開 & 列表過渡
- 狀態過渡
- 可復用性 & 組合
- 混入
- 自定義指令
- 渲染函數 & JSX
- 插件
- 過濾器
- 工具
- 生產環境部署
- 單文件組件
- 單元測試
- TypeScript 支持
- 規模化
- 路由
- 狀態管理
- 服務端渲染
- 內在
- 深入響應式原理
- 遷移
- 從 Vue 1.x 遷移
- 從 Vue Router 0.7.x 遷移
- 從 Vuex 0.6.x 遷移到 1.0
- 更多
- 對比其他框架
- 加入 Vue.js 社區
- 開發團隊