首頁 >web前端 >js教程 >Vue自訂指令及指令定義函數的具體分析(程式碼)

Vue自訂指令及指令定義函數的具體分析(程式碼)

不言
不言原創
2018-07-21 16:09:362070瀏覽

Vue自訂指令可以在全域或局部定義,Vue元件是html和程式碼的複用,而Vue指令是對DOM的擴充復用;下面我們就來具體看看Vue中自訂指令的分析。

1、Vue自訂指令:使用Vue.directive(id,definition)註冊全域自訂指令,使用元件的directives選項註冊局部自訂指令。

2、Vue 鉤子函數:

指令定義函數提供了幾個鉤子函數(可選):

bind:只呼叫一次,指令第一次綁定到元素時調用,用這個鉤子函數可以定義一個在綁定時執行一次的初始化動作。

inserted:被綁定元素插入父節點時調用(父節點存在即可調用,不必存在於 document 中)。

update:第一次是緊跟在 bind 之後調用,獲得的參數是綁定的初始值,之後被綁定元素所在的模板更新時調用,而不論綁定值是否變化。透過比較更新前後的綁定值,可以忽略不必要的模板更新(詳細的鉤子函數參數見下)。

componentUpdated:被綁定元素所在模板完成一次更新週期時呼叫。

unbind:只呼叫一次, 指令與元素解綁時呼叫。

3、Vue 鉤子函數的參數:(el, binding, vnode, oldVnode)

el:指令所綁定的元素,可以用來直接操作 DOM 。

binding:一個對象,包含以下屬性

##    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.a.b,modifiers的值為{'a ':true,'b':true}

vnode:Vue編譯的產生虛擬節點;

oldVnode:上一次的虛擬節點,僅在update和componentUpdated鉤子函式中可用。

<p id="app" v-demo:foo.a.b="message"></p>

Vue.directive(&#39;demo&#39;, {
  bind: function (el, binding, vnode) {
      console.log(&#39;bind&#39;);
    var s = JSON.stringify
    el.innerHTML =
      &#39;name: &#39;       + s(binding.name) + &#39;<br>&#39; +
      &#39;value: &#39;      + s(binding.value) + &#39;<br>&#39; +
      &#39;expression: &#39; + s(binding.expression) + &#39;<br>&#39; +
      &#39;argument: &#39;   + s(binding.arg) + &#39;<br>&#39; +
      &#39;modifiers: &#39;  + s(binding.modifiers) + &#39;<br>&#39; +
      &#39;vnode keys: &#39; + Object.keys(vnode).join(&#39;, &#39;)
  }
});
new Vue({
  el: &#39;#app&#39;,
  data: {
    message: &#39;hello!&#39;
  }
});

 4、函數簡寫:大多數情況下,我們可能想在 bind 和 update 鉤子上做重複動作,並且不想關心其它的鉤子函數。可以這樣寫:

Vue.directive(&#39;color-swatch&#39;, function (el, binding) {
  el.style.backgroundColor = binding.value
})

5、物件字面量:如果指令需要多個值,可以傳入一個 JavaScript 物件字面量。記住,指令函數能夠接受所有合法類型的 Javascript 表達式。

<p v-demo="{ color: &#39;white&#39;, text: &#39;hello!&#39; }"></p>

Vue.directive(&#39;demo&#39;, function (el, binding) {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text)  // => "hello!"
})

 範例解析:

<p id="app">
    <my-comp v-if="msg" :msg="msg"></my-comp>
    <button @click="update">更新</button>
    <button @click="uninstall">卸载</button>
    <button @click="install">安装</button>
</p>
<script type="text/javascript">
    Vue.directive(&#39;hello&#39;, {
        bind: function (el){
            console.log(&#39;bind&#39;);
        },
        inserted: function (el){
            console.log(&#39;inserted&#39;);
        },
        update: function (el){
            console.log(&#39;update&#39;);
        },
        componentUpdated: function (el){
            console.log(&#39;componentUpdated&#39;);
        },
        unbind: function (el){
            console.log(&#39;unbind&#39;);
        }
    });

    var myComp = {
        template: &#39;<h1 v-hello>{{msg}}</h1>&#39;,
        props: {
            msg: String
        }
    }

    new Vue({
        el: &#39;#app&#39;,
        data: {
            msg: &#39;Hello&#39;
        },
        components: {
            myComp: myComp
        },
        methods: {
            update: function (){
                this.msg = &#39;Hi&#39;;
            },
            uninstall: function (){
                this.msg = &#39;&#39;;
            },
            install: function (){
                this.msg = &#39;Hello&#39;;
            }
        }
    })
</script>

a、頁面載入時:bind inserted

b、更新元件:update componentUpdated

c、卸載元件:unbind

d、重新安裝元件:bind inserted

注意區別:bind與inserted:bind時父節點為null,inserted時父節點存在;update與componentUpdated:update是資料更新前, componentUpdated是資料更新後。

6.最後上一個實際開發的指令封裝實作

#基本想法

import store from &#39;@/store&#39;

export default {
  inserted(el, binding, vnode) {
    const { value } = binding
    const roles = store.state.permission.pagePermission
    if (value && typeof value === &#39;string&#39; && value.length > 0) {
      const hasPermission = roles.some(role => {
        return role.permission == value
      })
      if (!hasPermission) {
        el.parentNode && el.parentNode.removeChild(el)
      }
    } else {
      throw new Error(`need roles! Like v-permission="&#39;button&#39;"`)
    }
  }
}

 向外暴露api

import permission from &#39;./permission&#39;

const install = function(Vue) {
  Vue.directive(&#39;permission&#39;, permission)
}

if (window.Vue) {
  window[&#39;permission&#39;] = permission
  Vue.use(install) // eslint-disable-line
}

permission.install = install
export default permission

相關推薦:

vue自訂指令實作v-tap外掛

怎麼使用Vue的自訂指令完成一個下拉式選單

以上是Vue自訂指令及指令定義函數的具體分析(程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn