iT邦幫忙

第 12 屆 iThome 鐵人賽

0
自我挑戰組

跟 VueJS 認識的30天系列 第 19

[DAY19] 跟 Vue.js 認識的30天 - Vue 自定義指令(`directive`)

在粗淺的看過這一章時,覺得 Vue 真的有好多功能啊,目前的我似乎還是沒辦法很熟用 Vue 的每項語法,只希望未來在遇到各種問題時,我能有印象可以使用哪種語法。

自定義指令寫法

自定義指令分成2種寫法,分別是全局註冊及區域註冊:

  • 全局註冊

    Vue.directive('directiveName',{
      bind(el, binding, vnode) {
        // 指令第一次绑定到元素時调用,只調用一次。
      },
      inserted(el, binding, vnode) {
        // 被绑定元素插入父元素時调用
      },
      update(el, binding, vnode, oldVnode) {
        // 模組內的元素變動時調用
      },
      componentUpdated(el, binding, vnode, oldVnode){
        // 更新后调用。
      },
      unbind(el, binding, vnode){
        // 指令解除绑定
      }
    })
    
  • 區域註冊

    directives:{
      directiveName:{
        bind(el, binding, vnode) {
          // 指令第一次绑定到元素時调用,只調用一次。
        },
        inserted(el, binding, vnode) {
          // 被绑定元素插入父元素時调用
        },
        update(el, binding, vnode, oldVnode) {
          // 模組內的元素變動時調用
        },
        componentUpdated(el, binding, vnode, oldVnode){
          // 更新后调用。
        },
        unbind(el, binding, vnode){
          // 指令解除绑定
        }
      }
    }
    

自定義指令的鉤子函數及其參數

https://ithelp.ithome.com.tw/upload/images/20210212/20127553KJMeY634Jb.png

https://ithelp.ithome.com.tw/upload/images/20210212/20127553xNYBHuAkaV.png

上面2張圖是從 Vue 文件中擷取出來的,但光看說明還是不清楚裡面的配置,所以就讓我們來實際操作試試。

鉤子函數

<button @click.prevent="counts++">新增P tag</button>
<p v-for="count of counts" :key='count' v-border-color:top="Math.random().toString(10).substr(2,6)">我會變成隨機顏色</p>
<script>
Vue.directive("border-color", {
  bind(el, binding, vnode) {
    console.log("bind");
    console.log("el: ", el);
    console.log("binding: ", binding);
    console.log("vnode: ", vnode);
    el.style.color = `#${binding.value}`;
  },
  inserted(el, binding, vnode) {
    console.log("inserted");
    console.log("el: ", el);
    console.log("binding: ", binding);
    console.log("vnode: ", vnode);
  },
  update(el, binding, vnode, oldVnode) {
    console.log("update");
    console.log("el: ", el);
    console.log("binding: ", binding);
    console.log("vnode: ", vnode);
    console.log("oldVnode: ", oldVnode);
  },
  componentUpdated(el, binding, vnode, oldVnode) {
    console.log("componentUpdated");
    console.log("el: ", el);
    console.log("binding: ", binding);
    console.log("vnode: ", vnode);
    console.log("oldVnode: ", oldVnode);
  },
  unbind(el, binding, vnode) {
    console.log("unbind");
    console.log("el: ", el);
    console.log("binding: ", binding);
    console.log("vnode: ", vnode);
  }
});
</script>

畫面剛載入時,會執行 bind()inserted()

https://ithelp.ithome.com.tw/upload/images/20210212/20127553NP3KQUeS7W.png

當點擊了新增 P tag 的按鈕時,會先執行原本的第一個 P 標籤的 update()componentUpdated() ,之後執行新增的那個 P 標籤的 bind()inserted()

https://ithelp.ithome.com.tw/upload/images/20210212/20127553PjHjJEIkOy.png

也就是說會先執行完原本標籤的 update()componentUpdated() (不論原本標籤有幾個會都執行),才去執行新增標籤的 bind()inserted()

鉤子函數中的參數

  • el : 綁定該自定義指令的元素,可透過 el 直接操作該 DOM 元素。

  • binding : 擁有許多屬性,可以供使用。如下圖。

https://ithelp.ithome.com.tw/upload/images/20210212/20127553XRQAWb45Hc.png

  • vnodeoldVnode : 感覺不是很常會用到的東西,之後再找時間了解。

在 Vue 文件中重點提示了:

除了 el ,其餘的參數中的屬性只能讀取不能修改,如有需要在不同函數中共享一些數據的話,可以在 HTML 中透過 dataset (data-*)來設定。

動態綁定參數

<button @click.prevent="changeDirection">改變方向</button>
<p v-border-color:[direction]="Math.random().toString(10).substr(2,6)">我會變成隨機顏色</p>
<script>
const vm = new Vue({
  el: "#vm",
  data: {
    directions:['top','right','bottom','left'],
    direction:`top`
  },
  methods: {
    changeDirection() {
      this.direction =this.directions[Math.floor(Math.random()*4)]
    }
  }
});
</script>

透過 v-directiveName:[dynamicArgumentName] ,可以為該元素的自定義指令加上動態參數(可跟著模組資料進行更新)。

提醒一下,如果僅僅是變換綁定的參數,也會為該元素觸發 update()componentUpdated() 喔!

自定義指令值

特別把這個寫出來是因為剛開始練習時,一直無法正常運作,後來才發現這個值的使用方法跟 v-bind 的用法是相同的,值可以物件、陣列、數字、字串等等,但也因此如果這個值是單純字串的話,那麼就一定要加上 '' ,讓 Vue 知道這是字串,否則 Vue 會認為這是模組資料(data)的內容。

Demo:DAY19 | 跟 Vue.js 認識的30天 - Vue 模組自定義指令(directive)

參考資料

Vue.js - 自定义指令

Yes

Yes


上一篇
[DAY18]跟 Vue.js 認識的30天 - Vue 混入(`mixin`)
下一篇
[DAY20]跟 Vue.js 認識的30天 - Vue 插件(Plugin)
系列文
跟 VueJS 認識的30天21
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言