Vue插件開發詳解

爲什麼要開發插件?

插件是對Vue功能上的補充,比如可以設置頁面全局共享屬性,方法等。

目錄

依據官方文檔插件開發說明,插件開發有四種方式。

  1. 添加全局方法或者屬性;

  2. 添加 Vue 實例方法,通過把它們添加到 Vue.prototype 上實現。

  3. 通過全局 mixin 方法添加一些組件選項;

  4. 添加全局資源:指令/過濾器/過渡等;

  5. 一個庫,提供自己的 API,同時提供上面提到的一個或多個功能,

閱讀前必讀

  • Vue.js 的插件應該有一個公開方法 install。這個方法的第一個參數是 Vue 構造器,第二個參數是一個可選的選項對象. 比如:
export default{
    install:function (Vue,options) {  
        Vue.$globalFunction=function (num) { 
            return 2*num;
         };

         Vue.$globalVariable="我是mrgao";
    }
}

  • 開發插件時,給Vue/Vue實例添加方法或者屬性時,建議命名方式使用$開頭,這樣就不會存在和插件命名衝突。如果衝突了則優先使用組件屬性/方法。

一、添加全局方法和屬性

作用:

添加全局方法和屬性,所有組件都可共享方法和屬性,當某個組件更新了共享屬性,那麼其他組件也會同步更新。並非是組件實例之間的數據共享。

//1:編寫組件

export default{
    install:function (Vue,options) {  
        Vue.$globalFunction=function (num) { 
            return 2*num;
         };

         Vue.$globalVariable="我是mrgao";
    }
}

//2:聲明組件,注入組件
import install from "./plugins/demo.js";
Vue.use(install);

//3:組件樣例
<Poptip trigger="focus">
      <Input
        v-model="gloablFunc"
        prefix="logo-usd"
        placeholder="Enter number"
        style="width: 120px"
      />
      <div slot="content">{{ formatNumber }}</div>
</Poptip>
import Vue from "vue";
export default {
  data() {
    return {
      gloablFunc: ""
    };
  },

  computed: {
    formatNumber: function() {
      //調用全局共享方法
      return Vue.$globalFunction(this.gloablFunc);
    }
  }
};

二、給Vue實例添加方法和屬性

方式:使用Vue.prototype的方式給Vue實例添加方法和屬性

注意點:使用Vue.prototype的方式添加的屬性是不會在各個實例之間數據共享的。
比如A實例修改了某屬性,則B實例使用此屬性時不會是A修改的值。

//1:組件編寫 demo.js
export default {
  install: function(Vue, options) {
    Vue.prototype.$instanceFunction = function(num) {
      return 3 * num;
    };

    Vue.prototype.$instanceVar="我是實例變量";
  }
};

//2:組件聲明 main.js
import install from "./plugins/demo.js";
Vue.use(install);



//3:組件使用 Plugins.vue
...省略部分
<span>添加實例方法/屬性測試</span>
 <div>{{ instanceVar }}</div>

  mounted(){
      console.log(this.$instanceVar);
      this.instanceVar=this.$instanceVar;
      //this.instanceVar=this.$instanceFunction(20);
  }

三、通過混入 mixin 方法添加一些組件選項;

混入mixin作用:
將混入對象的方法/數據對象合併到改組件本身的方法/數據上;若存在同名的方法,則首先調用混入對象,再調用組件本身方法,若存在同名數據對象,則使用組件的數據對象

混入分爲局部混入和全局混入,一旦使用全局混入對象,將會影響到 所有 之後創建的 Vue 實例。請謹慎使用全局混入,儘可能使用局部混入。

1. 局部混入

此處借用官方的例子選項合併

  • 當組件和混入對象含有同名選項時,這些選項將以恰當的方式混合。比如,數據對象在內部會進行遞歸合併,在和組件的數據發生衝突時以組件數據優先。

  • 若存在同名方法則優先調用混入對象的方法。

  • 值爲對象的選項,例如 methods, components 和 directives,將被混合爲同一個對象。兩個對象鍵名衝突時,取組件對象的鍵值對。

var mixin = {
  data: function() {
    return {
      message: "hello",
      foo: "abc"
    };
  },
  created: function() {
    console.log("混入對象的鉤子被調用");
  },
  methods:{
      demo1(){
           console.log("混入demo1");
      },
      demo2(){
            console.log("混入demo2");
      }
  }
};

export default {
  mixins: [mixin],
  data: function() {
    return {
      message: "goodbye",
      bar: "def"
    };
  },
  created: function() {
       console.log('組件鉤子被調用')
    console.log(this.$data);
    //混入對象的鉤子被調用
    //組件鉤子被調用
    // => { message: "goodbye", foo: "abc", bar: "def" }
  },
  methods:{
      demo1(){
          console.log("組件demo1");
          
      }
  }
};

2. 全局混入

爲全局Vue實例混入一個created方法,在每一個實例調用本身的created之前都會首先調用混入的created。

通常我們可以使用全局混入對Vue實例注入統一處理統計


// 爲自定義的選項 'myOption' 注入一個處理器。
Vue.mixin({
    created: function () {
    //console.log("相信我,這個Log會在每一個Vue實例created之前調用");
        
      var myOption = this.$options.myOption
      if (myOption) {
        console.log(myOption)
      }
    }
  })

new Vue({
  myOption: 'hello! mrgao'
})
// => "hello!"

四、添加全局資源:指令,過濾器等

1. 添加自定義指令

除了核心功能默認內置的指令 (v-model 和 v-show等),Vue 也允許註冊自定義指令。

參考官方文檔:自定義指令

指令鉤子函數會被傳入以下參數:

  • el:指令所綁定的元素,可以用來直接操作 DOM 。
  • binding:一個對象,包含以下屬性:
    • name:指令名,不包括 v- 前綴。
    • value:指令的綁定值,例如:v-my-directive=“1 + 1” 中,綁定值爲 2。
    • oldValue:指令綁定的前一個值,僅在 update 和 componentUpdated 鉤子中可用。無論值是否改變都可用。
    • expression:字符串形式的指令表達式。例如 v-my-directive=“1 + 1” 中,表達式爲 “1 + 1”。
    • arg:傳給指令的參數,可選。例如 v-my-directive:foo 中,參數爲 “foo”。
    • modifiers:一個包含修飾符的對象。例如:v-my-directive.foo.bar 中,修飾符對象爲 { foo: true, bar: true }。
  • vnode:Vue 編譯生成的虛擬節點。移步 VNode API 來了解更多詳情。
  • oldVnode:上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。
//D.vue
<template>
  <div v-demo:foo.a.b="message"></div>
</template>

<script>
export default {
  data() {
    return {
      message: "我是demo"
    };
  }
};
//main.js
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 keys: ' + Object.keys(vnode).join(', ')
  }
})



結果爲:

name: "demo"
value: "我是demo"
expression: "message"
argument: "foo"
modifiers: {"a":true,"b":true}
vnode keys: tag, data, children, text, elm, ns, context, fnContext, fnOptions, fnScopeId, key, componentOptions, componentInstance, parent, raw, isStatic, isRootInsert, isComment, isCloned, isOnce, asyncFactory, asyncMeta, isAsyncPlaceholder

2. 添加過濾器


//1:編寫過濾器 currency.js
const digitsRE = /(\d{3})(?=\d)/g

export function currency (value, currency, decimals) {
  value = parseFloat(value)
  if (!isFinite(value) || (!value && value !== 0)) return ''
  currency = currency != null ? currency : '$'
  decimals = decimals != null ? decimals : 2
  var stringified = Math.abs(value).toFixed(decimals)
  var _int = decimals
    ? stringified.slice(0, -1 - decimals)
    : stringified
  var i = _int.length % 3
  var head = i > 0
    ? (_int.slice(0, i) + (_int.length > 3 ? ',' : ''))
    : ''
  var _float = decimals
    ? stringified.slice(-1 - decimals)
    : ''
  var sign = value < 0 ? '-' : ''
  return sign + currency + head +
    _int.slice(i).replace(digitsRE, '$1,') +
    _float
}


//2:聲明 main.js
import { currency } from "./currency";
Vue.filter("currency", currency);

//3:使用Productlist.vue
 <Tag type="dot" closable color="success">單價:{{ product.price | currency }}</Tag>

上述已經簡單講解了Vue插件開發的四種方式,最後一種方式,也就是將上述四種組合在一個install方法中即可。

歡迎Star

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章