Vue 自定義指令

前言 最近搞了畢設,須要實現一個場景,點擊一塊區域,彈出一個編輯區域,點擊頁面的其餘地方的時候,這個編輯區域就隱藏,本想一想以前寫模態框同樣寫個方法的時候,忽然
imagejavascript

以爲能夠嘗試用 vue 相關的東西優雅的解決這個事情,而後就學了下面的自定義指令了。html

1 Vue 自定義指令

1.1 定義

直接看官網的介紹吧(以爲官方文檔說的很清楚了,因此我基本都是抄他的了)。vue

除了核心功能默認內置的指令 (v-model 和 v-show),Vue 也容許註冊自定義指令。注意,在 Vue2.0 中,代碼複用和抽象的主要形式是組件。然而,有的狀況下,你仍然須要對普通 DOM 元素進行底層操做,這時候就會用到自定義指令。

1.2 基礎實現

這個在分兩種狀況,若是你想定義一個全局的自定義組件的話,那麼就在項目中的 main.js 裏面定義了,例如定義一個官網中的自動聚焦的指令java

// 註冊一個全局自定義指令 `v-focus`
Vue.directive('focus', {
  // 當被綁定的元素插入到 DOM 中時……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

要是你只是想定義一個局部的指令在某個組件內部用的話,那麼就在相應的組件內定義了node

// 跟 data(),methods:{} 那些同級寫了
directives: {
  focus: {
    // 指令的定義
    inserted: function (el) {
      el.focus()
    }
  }
}

定義完後咱們就能愉快的使用了express

<input v-focus>

1.2 鉤子函數

固然這個自定義指令不會就這麼一點東西啦,爲了解決一些現實中場景,Vue 給咱們一堆鉤子函數用來實現咱們的一些騷操做。具體以下 (均爲可選):async

  • bind:只調用一次,指令第一次綁定到元素時調用。在這裏能夠進行一次性的初始化設置。
  • inserted:被綁定元素插入父節點時調用 (僅保證父節點存在,但不必定已被插入文檔中)。
  • update:所在組件的 VNode 更新時調用,可是可能發生在其子 VNode 更新以前。指令的值可能發生了改變,也可能沒有。可是你能夠經過比較更新先後的值來忽略沒必要要的模板更新 (詳細的鉤子函數參數見下)。
  • componentUpdated:指令所在組件的 VNode 及其子 VNode 所有更新後調用。
  • unbind:只調用一次,指令與元素解綁時調用。

接下來咱們來看一下鉤子函數的參數 (即 el、binding、vnode 和 oldVnode)。ide

固然要想好好用用這寫鉤子函數,就要懂得用下面的這些參數函數

1.3 鉤子函數參數

指令鉤子函數會被傳入如下參數:ui

  • 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 來了解更多詳情。
  • oldVnode:上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。

而後官網有話說

除了 el 以外,其它參數都應該是隻讀的,切勿進行修改。若是須要在鉤子之間共享數據,建議經過元素的 dataset 來進行。

而後下面咱們給一個簡單的例子

// 在組件內部定義一個局部指令
directives:{
  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(', ')}`
    }
  }
}
 // 綁定到組件中的一個 div 中
<div v-demo:foo.a.b="message"></div>

而後咱們在網頁中就能夠看到這麼一堆文字了(固然下面的註釋是我本身寫的)

name: "demo" 
// 指定名稱
value: "Welcome to Your Vue.js App" 
// 指令綁定值
expression: "message" 
// 字符串形式的指令表達式
argument: "foo" 
// 傳給指令的參數
modifiers: {"a":true,"b":true} 
// 修飾符的對象
vnode keys: tag, data, children, text, elm, ns, context, fnContext, fnOptions, fnScopeId, key, componentOptions, componentInstance, parent, raw, isStatic, isRootInsert, isComment, isCloned, isOnce, asyncFactory, asyncMeta, isAsyncPlaceholder
// Vue 編譯生成的虛擬節點

1.4 函數簡寫

在不少時候,你可能想在 bindupdate 時觸發相同行爲,而不關心其它的鉤子。好比這樣寫:

colorSwatch: function colorSwitch(el, binding) {
  el.style.backgroundColor = binding.value
},

1.5 對象字面量

若是指令須要多個值,能夠傳入一個 JavaScript 對象字面量。記住,指令函數可以接受全部合法的 JavaScript 表達式。

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

就差很少這樣吧,想看個實例的話就看一下個人另一篇筆記《Vue 自定義指令實現點擊元素外觸發事件》

相關文章
相關標籤/搜索