自定義指令(Custom Directive)

by vivid 7. 八月 2019 07:48

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:
N190821001
出刊日期:2019/8/7

在這篇文章將延續本站《Vue.js入門》系列文章,來介紹如何設計自定義指令(Custom Directive)。回顧一下,指令(Directives)是前置「v-」符號的特殊特性(Attribute),讓你可以透過Vue套用一些特效到DOM物件上。預設Vue提供多樣的指令來供你使用,例如「v-if」、「v-show」、「v-else」、「v-model」、「v-bind」等等。

除了這些預設的指令之外,Vue可以讓你自定指令,在Vue 2.0版,建議達到重複使用的單位是「組件(Component)」,若在不同的組件之中,仍有需要共用的部分,就可以將之設計成自定義指令(Custom Directive)。

  • 了解指令(Directive)

一個指令只會有一個參數(Argument),指令語法:

v-指令名稱:參數

v-DirectiveName:Argument

我們回顧一下系列文章中介紹過的範例:

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>
<body>
  <div id="divMsg">
    <h1 v-on:click="showMsg"> {{ msg }} </h1>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    var vm = new Vue({
      el: '#divMsg',
      data: {
        msg: 'Hello',
      },
      methods: {
        showMsg: function (event) {
          alert(this.msg);
        }
      }
    });
  </script>
</body>

</html>

 

這個範例程式執行後,只要點選網頁中的<h1>標題,就會顯示一個「Hello」訊息。範例中使用了Vue內建的「v-on」指令:

<h1 v-on:click="showMsg">

這個範例中指令(Directive)的名稱是「on」,參數(Argument)是「click」,「showMsg」則是傳遞到指令的值。

指令中也可以包含修飾符(Modifier),語法如下 :

v-指令名稱:參數.修飾符

v-DirectiveName:Argument.Modifiers

指令後方可以加上零到多個修飾符(Modifier),例如我們可以修改上例,加上「once」修飾符,讓事件只有第一次生效:

<h1 v-on:click.once="showMsg"> {{ msg }} </h1>

此外,修飾符可以有多個,只要使用「.」號做區隔,語法如下:

v-指令名稱:引數.修飾符1.修飾符2

v-DirectiveName:Argument.Modifier1.Modifier2

 

自定義指令(Custom Directive)

指令定義物件(directive definition object)提供多種選擇性鉤子函式(hook function)可以使用,包含:「bind」、「inserted」、「update」、「componentUpdated」、「unbind」等等,最常使用的是「bind」與「update」這兩個函式,以下是使用自定義指令搭配「bind」函式的語法:

Vue.directive('自定義指令名稱', {
  bind(e1, binding, vnode) {
  
  }
})

 

接下來我們想要定義一個按鈕,利用自定義指令,讓它固定出現在網頁右下方,可以透過這個按鈕將網頁畫面捲動到網頁最上方,參考以下範例程式碼:

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>

  <div id="divMsg">
    <button v-gototop>^</button>
    <h1>Home</h1>
    Lorem ipsum, dolor sit amet consectetur adipisicing elit. Dignissimos, repellat! Eius eaque tenetur ad dignissimos
  ... 略

  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>
    Vue.directive("gototop", {
      bind(el, binding, vnode) {
        el.style.position = "fixed";
        el.style.width = "45px";
        el.style.height = "45px";
        el.style.opacity = "0.8";
        el.style.right = "50px";
        el.style.bottom = "30px";
        el.style.cursor = "pointer";
        el.style.border = "none";
        el.style.outline = "none";
        el.style.fontSize = "24px";
        el.style.background = "pink";
        el.addEventListener('click', () => {
          document.documentElement.scrollTop = 0;
        });
      }
    });

    var vm = new Vue({
      el: '#divMsg',
      data: {}
    });
  </script>
</body>

</html>

 

注意,自定義指令(Custom Directive)必需在Vue實體建立之前,先註冊好。範例中使用「Vue.directive」建立自定義指令(Custom Directive),名稱為「gototop」,然後在<button>標籤套用「v-gototop」指令。

「bind」函式包含三個參數:

  • 「el」:套用「v-gototop」指令的HTML項目。
  • 「binding」:參數物件,包含自定義指令的「name」、「modifiers」、「rawName」...等資訊。
  • 「vnode」:用來參考到virtual DOM。

我們在「bind」函式之中利用「style」屬性,設定了繫結對象(Button)的樣式,例如固定位置(position = "fixed")、寬度(width)、高度(hight)、透明度(opacity)...等等,並且註冊了「click」事件,當繫結對象被點選時,便設定「scrollTop」屬性為「0」,這樣便可以讓網頁捲動到最上方。這個範例程式的執行結果參考如下,網頁的右下方會出現回到最上面的按鈕(gototop):

clip_image002

圖 1:套用「v-gototop」指令的HTML項目。

當捲動到網頁下方,點選按鈕,畫面就會捲動到最上面,請參考下圖所示:

clip_image004

圖 2:點選HTML項目畫面就會捲動到最上面。

簡寫語法

大部分情況下,只需要使用到「bind」、「update」函式,如果不考慮到使用其它鉤子函式(hook function),可以使用簡寫版語法來定義自定義指令,語法如下:

Vue.directive('自定義指令名稱', function(e1, binding, vnode) {

})

上例的自定義指令範例可以改寫如下,執行將會得到相同的結果:

Vue.directive("gototop", function (el, binding, vnode) {

el.style.position = "fixed";

el.style.width = "45px";

el.style.height = "45px";

el.style.opacity = "0.8";

el.style.right = "50px";

el.style.bottom = "30px";

el.style.cursor = "pointer";

el.style.border = "none";

el.style.outline = "none";

el.style.fontSize = "24px";

el.style.background = "pink";

el.addEventListener('click', () => {

document.documentElement.scrollTop = 0;

});

});

傳遞值到自定義指令

上面的範例寫死了樣式,將繫結對象的背景顏色設定為「pink」色,如此不夠有彈性。我們要改良一下上述的自定義指令範例,讓你可以在HTML標籤套用「v-gototop」時,可以傳遞想使用的背景顏色到自定義指令,參考以下範例程式碼:

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>

  <div id="divMsg">
   <button v-gototop="'lightblue'">^</button>
    <h1>Home</h1>
    Lorem ipsum, dolor sit amet consectetur adipisicing elit. Dignissimos, repellat! Eius eaque tenetur ad dignissimos
...略
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>

    Vue.directive("gototop", function (el, binding, vnode) {
      el.style.background = binding.value;
      el.style.position = "fixed";
      el.style.width = "45px";
      el.style.height = "45px";
      el.style.opacity = "0.8";
      el.style.right = "50px";
      el.style.bottom = "30px";
      el.style.cursor = "pointer";
      el.style.border = "none";
      el.style.outline = "none";
      el.style.fontSize = "24px";
      el.addEventListener('click', () => {
        document.documentElement.scrollTop = 0;
      });
    });

    var vm = new Vue({
      el: '#divMsg',
      data: {}
    });
  </script>
</body>

</html>

 

我們在<button v-gototop="'lightblue'">標籤設定想傳遞的背景顏色為「'lightblue'」,傳遞的值是字串,因此使用單引號包起來,而在自定義指令中,便可以使用「binding.value」來取得傳遞過來的值。這樣我們的自訂義指令的彈性便會比較大。

 

傳遞參數(Argument)

在套用「v-gototop」自定義指令時,可以傳遞參數到自定義指令。我們來修改上個範例,讓自定義指令可以接收一個參數,名稱為「bgcolor」:

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title> Document </title>
</head>

<body>

  <div id="divMsg">
    <button v-gototop:bgcolor="'lightblue'">^</button>
    <h1>Home</h1>
    Lorem ipsum, dolor sit amet consectetur adipisicing elit. Dignissimos, repellat! Eius eaque tenetur ad dignissimos
...略
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script>

    Vue.directive("gototop", function (el, binding, vnode) {
      let bgColor = binding.arg === undefined ? "pink" : binding.value;
      el.style.background = bgColor;

      el.style.position = "fixed";
      el.style.width = "45px";
      el.style.height = "45px";
      el.style.opacity = "0.8";
      el.style.right = "50px";
      el.style.bottom = "30px";
      el.style.cursor = "pointer";
      el.style.border = "none";
      el.style.outline = "none";
      el.style.fontSize = "24px";
      el.addEventListener('click', () => {
        document.documentElement.scrollTop = 0;
      });
    });

    var vm = new Vue({
      el: '#divMsg',
      data: {}
    });
  </script>
</body>

</html>

 

「binding」物件包含一個「arg」屬性,裏頭便包含你傳入自定義指令的「bgcolor」,若套用自定義指令時,沒有設定「bgcolor」:

<button v-gototop="'lightblue'">^</button>

「binding.arg」就會是「undefined」,為了簡單起見,未設定「bgcolor」時,我們在程式中便設定使用預設的「pink」當背景顏色;若有設定「bgcolor」時,就會套用「lightblue」當背景顏色。這個範例程式的執行結果參考如下,使用參數設定背景顏色為藍色:

clip_image006

圖 3:使用參數設定背景顏色為藍色。

Tags:

.NET Magazine國際中文電子雜誌 | JavaScript | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List