Vue自定義指令使用方法詳解 和 使用場景

Vue自定義指令的使用,具體內容以下html

1.自定義指令的語法vue

Vue自定義指令語法以下:node

Vue.directive(id, definition)

傳入的兩個參數,id是指指令ID,definition是指定義對象。其中,定義對象能夠提供一些鉤子函數web

鉤子函數express

一個指令定義對象能夠提供以下幾個鉤子函數 (均爲可選):api

  • bind:只調用一次,指令第一次綁定到元素時調用。在這裏能夠進行一次性的初始化設置。app

  • inserted:被綁定元素插入父節點時調用 (僅保證父節點存在,但不必定已被插入文檔中)。ide

  • update:所在組件的 VNode 更新時調用,可是可能發生在其子 VNode 更新以前。指令的值可能發生了改變,也可能沒有。可是你能夠經過比較更新先後的值來忽略沒必要要的模板更新 (詳細的鉤子函數參數見下)。函數

咱們會在稍後討論渲染函數時介紹更多 VNodes 的細節。動畫

  • componentUpdated:指令所在組件的 VNode 及其子 VNode 所有更新後調用。

  • unbind:只調用一次,指令與元素解綁時調用。

接下來咱們來看一下鉤子函數的參數 (即 elbindingvnode 和 oldVnode)。

鉤子函數參數

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

  • el:指令所綁定的元素,能夠用來直接操做 DOM 。
  • binding:一個對象,包含如下屬性:vnode:Vue 編譯生成的虛擬節點。移步 VNode API 來了解更多詳情。
    • 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 }
  • oldVnode:上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。

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

這是一個使用了這些屬性的自定義鉤子樣例:

Vue.directive('my-directive', { bind: function(){ //作綁定的準備工做
 //好比添加事件監聽器,或是其餘只須要執行一次的複雜操做
 }, inserted: function(){ //...
 }, update: function(){ //根據得到的新值執行對應的更新
 //對於初始值也會調用一次
 }, componentUpdated: function(){ //...
 }, unbind: function(){ //作清理操做
 //好比移除bind時綁定的事件監聽器
 }

官網文檔:https://cn.vuejs.org/v2/guide/custom-directive.html

使用場景

  • 代碼複用和抽象的主要形式是組件
  • 當須要對普通 DOM 元素進行底層操做,此時就會用到自定義指令
  • 可是,對於大幅度的 DOM 變更,仍是應該使用組件

3. 示例

3.1 輸入框自動聚焦

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

3.2 下拉菜單

  • 點擊下拉菜單自己不會隱藏菜單
  • 點擊下拉菜單之外的區域隱藏菜單
Vue.directive('clickoutside', { bind(el, binding) { function documentHandler(e) { if (el.contains(e.target)) { return false } if (binding.expression) { binding.value(e) } } el.__vueMenuHandler__ = documentHandler document.addEventListener('click', el.__vueMenuHandler__) }, unbind(el) { document.removeEventListener('click', el.__vueMenuHandler__) delete el.__vueMenuHandler__ } }) new Vue({ el: '#app', data: { show: false }, methods: { handleHide() { this.show = false } } })

 

<div class="main" v-menu="handleHide">
  <button @click="show = !show">點擊顯示下拉菜單</button>
  <div class="dropdown" v-show="show">
    <div class="item"><a href="#">選項 1</a></div>
    <div class="item"><a href="#">選項 2</a></div>
    <div class="item"><a href="#">選項 3</a></div>
  </div>
</div>

 

3.3 相對時間轉換

相似微博、朋友圈發佈動態後的相對時間,好比剛剛、兩分鐘前等等

<span v-relativeTime="time"></span> new Vue({ el: '#app', data: { time: 1565753400000 } }) Vue.directive('relativeTime', { bind(el, binding) { // Time.getFormatTime() 方法,自行補充 el.innerHTML = Time.getFormatTime(binding.value) el.__timeout__ = setInterval(() => { el.innerHTML = Time.getFormatTime(binding.value) }, 6000) }, unbind(el) { clearInterval(el.innerHTML) delete el.__timeout__ } })

 

3.4 滾動動畫

<div id="app">
  <h1 class="centered">Scroll me</h1>
  <div class="box" v-scroll="handleScroll">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. A atque amet harum aut ab veritatis earum porro praesentium ut corporis. Quasi provident dolorem officia iure fugiat, eius mollitia sequi quisquam.</p>
  </div>
</div>
Vue.directive('scroll', { inserted: function(el, binding) { let f = function(evt) { if (binding.value(evt, el)) { window.removeEventListener('scroll', f) } } window.addEventListener('scroll', f) } }) // main app
new Vue({ el: '#app', methods: { handleScroll: function(evt, el) { if (window.scrollY > 50) { TweenMax.to(el, 1.5, { y: -10, opacity: 1, ease: Sine.easeOut }) } return window.scrollY > 100 } } })
body { font-family: 'Abhaya Libre', Times, serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; background: #000; color: #fff; overflow-x: hidden;
} h1, h2, h3, h4 { font-family: 'Fira Sans', Helvetica, Arial, sans-serif; font-weight: 800;
} .centered { margin: 0 auto; display: table; font-size: 60px; margin-top: 100px;
} .box { border: 1px solid rgba(255, 255, 255, 0.5); padding: 8px 20px; line-height: 1.3em; opacity: 0; color: white; width: 200px; margin: 0 auto; margin-top: 30px; transform: translateZ(0); perspective: 1000px; backface-visibility: hidden; background: rgba(255, 255, 255, 0.1);
} #app { height: 2000px;
}


自定義指令:
屬性:

Vue.directive(指令名稱,function(參數){
this.el -> 原生DOM元素
});

<div v-red="參數"></div>

指令名稱: v-red -> red

* 注意: 必須以 v-開頭

拖拽:
-------------------------------
自定義元素指令:(用處不大)
Vue.elementDirective('zns-red',{
bind:function(){
this.el.style.background='red';
}
});
------------------------------------------------
@keydown.up
@keydown.enter

@keydown.a/b/c....

自定義鍵盤信息:
Vue.directive('on').keyCodes.ctrl=17;
Vue.directive('on').keyCodes.myenter=13;
------------------------------------------------

相關文章
相關標籤/搜索