VUE2第五天學習---自定義指令

龍恩0707發表於2017-05-09

閱讀目錄

1.理解VUE中的自定義指令

預設核心指令有 (v-model 和 v-show), 但是有時候我們需要用到自定義指令,在vue中,程式碼複用主要形式和抽象是元件,但是在有的情況下,我們仍然需要對DOM元素進行底層操作,所以這個時候我們需要用到自定義指令。

比如下面的一個input框,當頁面載入時,元素將獲得焦點,我們還沒有點選input框,input就獲得焦點了,如下demo程式碼:

<!DOCTYPE html>
<html>
  <head>
    <title>演示Vue</title>
    <style>

    </style>
  </head>
  <body>
    <div id='demo'>
      <input v-focus>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">

    // 註冊一個全域性定義指令 v-focus
    Vue.directive('focus', {

      // 繫結元素插入到DOM 中
      inserted: function (el) {
        // 聚焦元素
        el.focus()
      }
    })
    new Vue({
      el: '#demo'
    })
  </script>
</html>

檢視效果

上面的是全域性定義指令 v-foucs, 當然我們也可以區域性定義,如下程式碼:

<!DOCTYPE html>
<html>
  <head>
    <title>演示Vue</title>
    <style>

    </style>
  </head>
  <body>
    <div id='demo'>
      <input v-focus>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    new Vue({
      el: '#demo',
      directives: {
        focus: {
          // 指令的定義
          inserted: function (el) {
            // 聚焦元素
            el.focus()
          }
        }
      }
    })
  </script>
</html>

檢視效果

然後我們就可以在任何input元素框或者textarea使用 v-focus 了,如下程式碼:

<input v-focus />

2. 指令定義函式提供瞭如下幾個鉤子函式(根據VUE教程來):
bind: 只呼叫一次,指令第一次繫結到元素時呼叫,也就是說初始化時候呼叫一次。
inserted: 被繫結元素插入父節點時呼叫(父節點需要存在才會呼叫)。
update: 被繫結元素所在的模板更新時呼叫(通過比較更新前後的繫結值)。
componentUpdated: 被繫結元素所在模板完成一次更新週期時呼叫。
unbind: 指令與元素解綁時呼叫,只呼叫一次,和bind對應。

上面幾個鉤子函式有如下引數 (el, binding, vnode, oldVnode)
el: 指令所繫結的元素,可用來直接操作DOM。
binding: {Object} obj有如下屬性:
name: 指令名,不包括 v- 字首
value: 指令繫結值。比如 v-my-directive = '1+1', 那麼value就是2.
oldValue: 指令繫結的前一個值,僅在 update 和 componentUpdated 鉤子中可用。無論值是否改變都可用。
expression: 繫結值的字串形式。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"。
arg: 傳給指令的引數。例如 v-my-directive:foo, arg 的值是 "foo"。
modifiers: 一個包含修飾符的物件。 例如: v-my-directive.foo.bar, 修飾符物件 modifiers 的值是 { foo: true, bar: true }。

vnode: Vue編譯生成的虛擬節點。
oldVnode: 上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。

注意: 除了 el 之外,其它引數都應該是隻讀的,儘量不要修改他們。如果需要在鉤子之間共享資料,建議通過元素的 dataset 來進行。

如下demo程式碼:

<!DOCTYPE html>
<html>
  <head>
    <title>演示Vue</title>
    <style>

    </style>
  </head>
  <body>
    <div id='demo' v-demo:hello.a.b='message'>
      
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    Vue.directive('demo', {
      bind: function(el, binding, vnode) {
        var s = JSON.stringify;
        el.innerHTML = 
          'name: '       + s(binding.name) + '<br/>' + 
          'value: '      + s(binding.value) + '<br/>' + 
          'expression: ' + s(binding.expression) + '<br/>' + 
          'argument: '   + s(binding.arg) + '<br/>' + 
          'modifiers: '  + s(binding.modifiers) + '<br/>' + 
          'vnode: '      + Object.keys(vnode).join(', ')
      }
    })
    new Vue({
      el: '#demo',
      data: {
        message: 'hello!'
      }
    })
  </script>
</html>

檢視效果

物件字面量
如果指令需要多個值,可以傳入一個 JavaScript 物件字面量。
如下程式碼:

<!DOCTYPE html>
<html>
  <head>
    <title>演示Vue</title>
    <style>

    </style>
  </head>
  <body>
    <div id='demo' v-demo="{ color: 'white', text: 'hello!' }">
      
    </div>
  </body>
  <script src="./vue.js"></script>

  <script type="text/javascript">
    Vue.directive('demo', function (el, binding) {
      console.log(binding.value.color) // => "white"
      console.log(binding.value.text)  // => "hello!"
    })
    new Vue({
      el: '#demo'
    })
  </script>
</html>

檢視效果

在控制檯可以看到輸出了字串了。

2. Vue.js自定義指令的用途。
上面是教程中的一些demo,但是在實際當中我們需要用到什麼地方呢?我們可以預想到可以使用到預載入資料的地方,比如預載入圖片,由於圖片載入需要一些時間,因此我們先載入一張佔位符圖片,
等圖片真正載入完成時候,才載入真正的圖片,這樣的使用者體驗效果更能更好點。下面是使用vue自定義指令來實現這個功能,程式碼如下:

 

<!DOCTYPE html>
<html>
  <head>
    <title>演示Vue</title>
    <style>
      img { width: 180px; height: 180px; overflow: hidden;}
    </style>
  </head>
  <body>
    <div id='demo'>
      <img v-for='item in list' v-img='item.url'/>
    </div>
  </body>
  <script src="./vue.js"></script>

  <script type="text/javascript">
    Vue.directive('img', {
      inserted: function(el, binding) {
        console.log(el)
        // 下面使用一張背景顏色來演示一下,
        var color = Math.floor(Math.random()*1000000);
        el.style.backgroundColor = '#' + color; // 隨機的背景顏色

        var img = new Image();
        img.src = binding.value; 
        img.onload = function() {
          el.style.backgroundImage = 'url(' + binding.value + ')';
        }
      }
    });
    new Vue({
      el: '#demo',
      data: {
        list: [
          {
            url: 'http://img.alicdn.com/imgextra/i3/730692984/TB2.dQMdxXkpuFjy0FiXXbUfFXa_!!730692984-0-beehive-scenes.jpg_180x180q70'
          },
          {
            url: 'http://img.alicdn.com/imgextra/i2/730692984/TB239AJdw0kpuFjSspdXXX4YXXa_!!730692984-0-beehive-scenes.jpg_180x180q70'
          },
          {
            url: 'http://img.alicdn.com/imgextra/i4/730692984/TB29TsZdrVkpuFjSspcXXbSMVXa_!!730692984-0-beehive-scenes.jpg_180x180q70'
          }
        ]
      }
    })
  </script>
</html>

檢視效果

如上演示可以看到,剛開始載入頁面的時候,有那麼一瞬間先是背景顏色 最後是圖片,這裡只是簡單的演示一下,在實際使用中,我們可以先放一張預載入的圖片,當真正圖片載入完成的時候,才顯示真正的圖片,省的在圖片未載入完成的時候,背景圖片是空白的效果就不是很好了。

相關文章