Vue 中「自定義指令」的魅力

Vue 中有許多的指令提供咱們使用。它可讓你進行一些模版的操做。html

可是內置指令,在實際的開發過程當中可能這些並不能知足全部的需求。因此 Vue 給咱們提供來一個靈活的方法「自定義指令」。node

說自定義指令以前,先看看什麼叫「指令」。express

指令的概念

指令是指能夠控制操做 DOM 的一些小命令,一般以 v- 前綴出現的特殊特性。bash

例如咱們常用的v-ifv-showv-bindv-onv-html等。app

使用指令時,你能夠傳遞值,字符串,也能夠給指令添加參數,修飾符等等。好比:函數

1.傳遞值ui

<p v-if="isShow">你好,我是六哥</p>
let vm = new Vue({
  el: "#app",
  data: {
    isShow: true
  }
});
複製代碼

2.字符串spa

<p v-text="'hello world'"></p>
複製代碼

3.添加參數code

// class,style 就是傳給指令的參數

<div v-bind:class="classObj"></div>
<div v-bind:style="classObj"></div>
複製代碼

4.修飾符component

// prevent 指令的修飾符

<button v-on:submit.prevent="onSubmit"></button>
複製代碼

以上是你常用指令的方式,瞭解這些以後,它能夠幫助咱們更好的認識自定義指令的 一些參數問題。下面就來看看自定義指令。

自定義指令

指令的註冊方式和「過濾器」、「混入」、「組件」註冊的方式同樣都分爲兩種:一是全局註冊,二是局部註冊。

1.全局註冊

Vue.directive('name', {})
複製代碼

2.局部註冊

directives: {
    name: {}
}
複製代碼

而後在模版中直接使用便可。

<p v-name>你好,六哥在這</p>
複製代碼

我我的更傾向於使用全局註冊的方式,由於既然已經使用了自定義指令,應該是通用,可複用的。

因此提供整個項目使用的指令才更有價值,而不只僅只限於某個組件內部。若是單一地方使用直接把功能摟出就好了,何須費這力氣。

繼續來看具體的實現方式。

Vue 提供了自定義指令的幾個鉤子函數:

  • bind:指令第一次綁定到元素時調用,只執行一次。
  • inserted:被綁定的元素,插入到父節點的 DOM 中時調用。
  • update:組件更新時調用。
  • componentUpdated:組件與子組件更新時調用。
  • unbind:指令與元素解綁時調用,只執行一次。

除update 與 componentUpdated 鉤子函數以外,每一個鉤子函數都含有 elbindingvnode 這三個參數。

oldVnode 只有在 update 與 componentUpdated 鉤子中生效。

參數el 就是指令綁定的 DOM 元素,而binding是一個對象,它包含一下屬性:namevalueoldValueexpressionargmodifiers

另外值得注意的一點是,除了 el 以外,bindingvnode 屬性都是隻讀的。

熟悉指令的建立方式與參數以後,咱們就用它來建立一個案例。

建立自定義指令

Loading 是項目中最多見的一個小功能,別看它功能小,可是起到的做用卻很大,手動建立一個 Loading 指令。

Vue.directive("loading", {
  bind(el, binding) {
    if (binding.value) {
      let div = document.createElement("div");
      div.className = "loading-parent";
      div.innerHTML = `
        <div class="loading-spinner"><i class='el-icon-loading'></i></div>
      `;
      el.appendChild(div);
    }
  },
  update(el, binding) {
    if (binding.value) {
      let div = document.createElement("div");
      div.className = "loading-parent";
      div.innerHTML = `
        <div class="loading-spinner"><i class='el-icon-loading'></i></div>
      `;
      el.appendChild(div);
      el.load = div;
    } else {
      el.load && el.load.parentNode && el.load.parentNode.removeChild(el.load);
    }
  }
});
複製代碼

而後咱們直接就能夠在模版中使用了。

<div v-loading="loading" class="box"></div>
複製代碼

你也看出來了不少代碼是重複的,怎麼辦呢?

Vue 中給咱們提供了簡寫方式。當只有這兩個鉤子函數時bindupdate,咱們能夠簡寫以下。

Vue.directive("loading", function(el, binding) {
  if (binding.value) {
    let div = document.createElement("div");
    div.className = "loading-parent";
    div.innerHTML = `
        <div class="loading-spinner"><i class='el-icon-loading'></i></div>
      `;
    el.appendChild(div);
    el.load = div;
  } else {
    el.load && el.load.parentNode && el.load.parentNode.removeChild(el.load);
  }
});
複製代碼

咱們實現了一個很是簡單的指令,但還不夠靈活,好比我想添加 loading 的背景色,修改圖標的顏色怎麼辦呢?

這時候就須要給指令傳入多個值,改造下實現背景與圖標顏色。

Vue.directive("loading", function(el, binding) {
  if (binding.value) {
    let div = document.createElement("div");
    div.className = "loading-parent";
    div.style.backgroundColor = binding.value.background;
    div.style.color = binding.value.color;
    div.innerHTML = `
        <div class="loading-spinner"><i class='el-icon-loading'></i></div>
      `;
    el.appendChild(div);
    el.load = div;
  } else {
    el.load && el.load.parentNode && el.load.parentNode.removeChild(el.load);
  }
});
複製代碼

直接使用

<div v-loading="{color: 'white', background: '#000'}">我能夠擁有更多屬性</div>
複製代碼

在文章開始咱們介紹指令時,還說到指令的「參數」與「修飾符」這裏我就很少介紹了,你們不妨本身去嘗試一下吧。體驗下自定義指令的魅力。

若是文章對你有啓發,記得給個贊哦。

公衆號:六小登登,更多幹貨文章。

人人均可以成爲高手。一個愛寫做的技術人。歡迎交流。

相關文章
相關標籤/搜索