天天看點

vue3 基礎-自定義指令 directive

自定義指令 v-xxx 的 directive

上篇内容是關于 mixin 混入的一些操作, 也是關于代碼複用層面的, 本篇講自定義指令 directive 也是為了實作複用而設計的一些小功能啦.

先來看看, 如果不用 directive 的場景下, 如何進行代碼複用.

<!DOCTYPE html>
<html lang="en">

<head>
  <title>不用 directive 時</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    const app = Vue.createApp({
      // 當頁面加載完就讓其自動獲得焦點
      mounted () {
        this.$refs.input1.focus()
        this.$refs.input2.focus()
        this.$refs.input3.focus()
      },
      template: `
      <div>
        <input ref="input1" />
        <input ref="input2" />
        <input ref="input3" />
      </div>
      `
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>      

可以看到這裡的 this.$refs.input2.focus( ) 被重複調用了3次, 這種寫法是沒有能實作咱說的複用的. 而 derective 則就是為了将其封裝為一個指令而設計的啦.

全局指令 directive

先來一個直覺示範, 如上例我們自定義一個名為 focus 的全局指令, 功能是使其 dom 能獲得焦點.

<!DOCTYPE html>
<html lang="en">

<head>
  <title>自定義全局指令</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    const app = Vue.createApp({
      template: `
      <div>
        <input ref="input1" v-focus />
      </div>
      `
    })

    // 自定義一個全局指令 focus, 作用是讓其 dom 獲得焦點
    app.directive('focus', {
      mounted (el) {
        el.focus()
      }
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>      

全局指令即可通過 app.directive('xxx', { }) 來定義, 使用的使用直接在 dom 中通過 v-xxx 即可.

局部指令 directive

同局部元件, 局部 mixin 幾乎一樣的操作, 就是在 vue 之外寫一個對象, 然後通過 vue 中的某個屬性進行引入啦.

<!DOCTYPE html>
<html lang="en">

<head>
  <title>自定義局部指令</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    // 自定義局部指令
    const myDirective = {
      focus: {
        mounted (el) {
          el.focus()
        }
      }
    }

    const app = Vue.createApp({
      directives:myDirective,
      template: `
      <div>
        <input ref="input1" v-focus />
      </div>
      `
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>      

需要注意這裡的引入寫法是鍵值對的方式哦, 感覺也是亂七八糟的:

directives:myDirective      

當然關于指令的作用周期也可以是結合咱的8大生命周期函數如下:

  • beforCreate, created: 在 vue 執行個體建立前, 後 的自動執行
  • beforMount, mounted: 在 vue 元件渲染到頁面前, 後 的自動執行
  • beforUpdate, updated: 在 data 資料變化前, 資料變化後并渲染後 的自動執行
  • beforUnmount, unmounted: 在 vue 執行個體被銷毀 前, 後 的自動執行

自定義指令開發

這裡簡單來開發一個指令叫 v-position 實作元素的位置自定義效果.

<!DOCTYPE html>
<html lang="en">

<head>
  <title>自定義指令開發</title>
  <script src="https://unpkg.com/vue@3"></script>
  <style>
    .test {
      position: absolute;
      height: 100px;
      background: orange;
    }
  </style>
</head>
<body>
  <div id="root"></div>
  <script>
    const app = Vue.createApp({
      data () {
        return { num: 200 }
      },
      template: `
      <div>
        <div v-position="num" class="test">v-position 測試</div>
      </div>
      `
    })

    // 自定義全局指令 v-position 開發
    app.directive('position', {
      mounted (el, binding) {
        el.style.top = binding.value + 'px'
      },
      updated (el, binding) {
        el.style.top = binding.value + 'px'
      }
    })
    
    const vm = app.mount('#root')

  </script>
</body>

</html>      

當隻有 mounted 和 updated 的時候可以有個簡寫如下:

app.directive('position', (el, binding) => {
el.style.top = binding.value + 'px'
})      

結合之前我們對指令傳參的應用, 如 v-on:click = 'xxx' 的這種寫法, 也是可以将參數傳遞給到 binding 的 arg中的, 那這樣就可以對咱的這個 position 做 top, right, bottom, left 等參數啦.

<!DOCTYPE html>
<html lang="en">

<head>
  <title>自定義指令開發</title>
  <script src="https://unpkg.com/vue@3"></script>
  <style>
    .test {
      position: absolute;
      height: 100px;
      background: orange;
    }
  </style>
</head>
<body>
  <div id="root"></div>
  <script>
    const app = Vue.createApp({
      data () {
        return { num: 200 }
      },
      // v-position:xxx 這裡就可以傳參數啦
      template: `
      <div>
        <div v-position:left="num" class="test">v-position 測試</div>
      </div>
      `
    })

    // 自定義全局指令 v-position 開發
    app.directive('position', (el, binding) => {
      // console.log('binding:', binding)
      el.style[binding.arg] = binding.value + 'px'
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>      

其實核心就是這個 binding 對象啦:

app.directive('position', (el, binding) => {
  el.style[binding.arg] = binding.value + 'px'
})      

小結

  • 自定義指令 directive 結合生命周期函數可是實作代碼的複用
  • 分為全局指令 app.directive( ) 和局部指令 directives: xxx 的形式
  • 自定義開發即是對傳輸的 el 進行操作, 也可以通過 binding 對象進行傳參 arg

繼續閱讀