天天看點

vue3的自定義指令

除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外,Vue 還允許你注冊自定義的指令 (Custom

Directives)。

1.自定義指令的目的和簡單介紹

自定義指令主要是為了重用涉及普通元素的底層 DOM 通路的邏輯。

一個自定義指令由一個包含類似元件生命周期鈎子的對象來定義。鈎子函數會接收到指令所綁定元素作為其參數。

舉例:

在某個場景下,需要一進入頁面或者打開某個彈窗就聚焦到指定的輸入框。

局部的寫法:

<script setup>
const vFocus = {
  created(el, binding,) {
  },
  beforeMount(el, binding,) {
  },
  mounted(el) {
    el.focus()
  },
  beforeUpdate(a,b,c,prevNode) { //! 第四個參數 prevNode 隻在beforeUpdate和updated才有!
  },
  updated() {},
  beforeUnmount() {
    // 當指令綁定的元素 的父元件銷毀前調用。  <簡單講,指令元素的父元件銷毀前調用>
  },
  unmounted() {},// 當指令與元素解除綁定且父元件已銷毀時調用。
}
</script>

<template>
  <input v-focus>
</template>      

全局的寫法:

import { createApp } from 'vue'
const app = createApp(App)
app.directive('focus',{
  created(el, binding,) {
  },
  beforeMount(el, binding,) {
  },
  mounted() {
    el.focus()
  },
  beforeUpdate(a,b,c,prevNode) { //! 第四個參數 prevNode 隻在beforeUpdate和updated才有!
  },
  updated() {},
  beforeUnmount() {
    // 當指令綁定的元素 的父元件銷毀前調用。  <簡單講,指令元素的父元件銷毀前調用>
  },
  unmounted() {},// 當指令與元素解除綁定且父元件已銷毀時調用。
})      
使用全局注冊需注意得寫在mount(‘#app’)之前,否則會報錯
vue3的自定義指令

我門可以發現對比vue2來看vue3裡自定義指令似乎在生命周期這塊發生了某些變化,下面我們來看看具體的。

注意:後面的示例都用局部的自定義指令來講解。

2.對比vue2自定義指令的生命周期

vue2自定義指令生命周期

  • bind: function () {},
  • inserted: function () {},
  • update: function () {},
  • componentUpdated: function () {},
  • unbind: function () {}

vue3自定義元件生命周期

  • created:在綁定元素的 attribute 或事件監聽器被應用之前調用。在指令需要附加在普通的 v-on

    事件監聽器調用前的事件監聽器中時,這很有用。

  • beforeMount:當指令第一次綁定到元素并且在挂載父元件之前調用。
  • mounted:在綁定元素的父元件被挂載後調用。
  • beforeUpdate:在更新包含元件的 VNode 之前調用。
  • updated:在包含元件的 VNode 及其子元件的 VNode 更新後調用。
  • beforeUnmount:在解除安裝綁定元素的父元件之前調用
  • unmounted:當指令與元素解除綁定且父元件已解除安裝時,隻調用一次。

這些生命周期都會接受以下幾個參數:

el, binding, vnode,      

他們分别代表什麼意思呢?

el:指令綁定到的元素。這可以用于直接操作 DOM。

binding:一個對象,包含以下屬性。

  • arg:傳遞給指令的參數 (如果有的話)。例如在 v-my-directive:foo 中,參數是 “foo”。
  • dir:指令的定義對象。
  • instance:使用該指令的元件執行個體。
  • modifiers:一個包含修飾符的對象 (如果有的話)。例如在 v-my-directive.foo.bar 中,修飾符對象是 {foo: true, bar: true }。
  • oldValue:之前的值,僅在 beforeUpdate 和 updated 中可用。無論值是否更改,它都可用。
  • value:傳遞給指令的值。例如在 v-my-directive=“1 + 1” 中,值是 2。

vnode:代表綁定元素的底層 VNode。

prevNode:之前的渲染中代表指令所綁定元素的 VNode。僅在 beforeUpdate 和 updated 鈎子中可用。

這樣看可能抽象了點,我們在指令的mounted裡列印下這4個參數,可見:

<script setup>
const vFocus = {
  created(el, binding,) {
  },
  beforeMount(el, binding,) {
  },
  mounted(el,binding, vnode,prevVnode) {
    console.log('el--',el)
    console.log('binding-',binding)
    console.log('vnode-',vnode)
    console.log('prevVnode-',prevVnode)
    console.log()
    el.focus()
  },
  beforeUpdate(a,b,c,prevNode) { //! 第四個參數 prevNode 隻在beforeUpdate和updated才有!
  },
  updated() {},
  beforeUnmount() {
    // 當指令綁定的元素 的父元件銷毀前調用。  <簡單講,指令元素的父元件銷毀前調用>
  },
  unmounted() {},// 當指令與元素解除綁定且父元件已銷毀時調用。
}
</script>      
vue3的自定義指令

3.舉兩個栗子

我們主要看el和binding。

我們通過自定義指令來畫一個固定寬高和背景色的方塊吧!

//name:自定義參數,hqg:自定義修飾符
<div v-myDirective:name.hqg="{background: '#ccc', width: '200px', height: '200px'}">
  這是一個div
</div>
const vMyDirective = {
  mounted(el,binding, vnode,prevVnode) {
    console.log('binding',binding)
    el.style.background = binding.value.background
    el.style.width = binding.value.width
    el.style.height = binding.value.height
  },
}      

最後注意

繼續閱讀