vue外掛編寫小記

小菜鳥愛程式設計發表於2018-03-24

一、為什麼要自己動手寫外掛呢,原因有二:

  其一:是因為最近產品了提了一個在web端接收,訊息通知的需求,產品要求在若干個頁面內如果有訊息,就要彈出訊息彈窗展示給使用者,略加思索之後,第一反應就是寫個訊息的元件,在需要的頁面引入,不過寫好之後,發現這樣寫好麻煩,是不是可以寫個外掛在全域性一次性引入呢?

  其二:純粹的想學習一下vue的外掛是如何開發的

二、既然有想法了,那就開始寫唄,先去檢視了vue的官方文件,官方文件介紹如下:

外掛通常用於為 Vue 新增全域性級別的功能。然而對於外掛,並沒有嚴格限定其使用範圍 – 下面是常見的幾種外掛型別:

新增一些全域性方法或屬性。

新增一個或多個全域性資源(asset):指令(directives)/過濾器(filters)/過渡(transitions) 等。

通過全域性 mixin,新增一些元件選項。

新增一些 Vue 例項方法,通過把這些方法新增到 Vue.prototype 上實現。

一個可以提供 API 的庫(library),與此同時也是以上功能的組合。

Vue.js 外掛應該暴露一個 install 方法。此方法在呼叫時,將 Vue 建構函式作為第一個引數傳入,以及將一個可選的選項作為第二個引數傳入:

MyPlugin.install = function (Vue, options) {
  // 1. 新增全域性方法或屬性
  Vue.myGlobalMethod = function () {
    // 一些邏輯……
  }

  // 2. 新增一個全域性資源(asset)
  Vue.directive(`my-directive`, {
    bind (el, binding, vnode, oldVnode) {
      // 一些邏輯……
    }
    ...
  })

  // 3. 注入一些元件選項
  Vue.mixin({
    created: function () {
      // 一些邏輯……
    }
    ...
  })

  // 4. 新增一個例項方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // 一些邏輯……
  }
}
通過呼叫全域性方法 Vue.use() 使用外掛:

// 呼叫 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)
可以根據情況,傳入一些可選的選項:

Vue.use(MyPlugin, { someOption: true })
Vue.use 會自動阻止多次使用同一個外掛,所以對於同一個外掛的多次呼叫,將只安裝一次。

三、看完文件我們就開始動手寫唄(以loading外掛為例)

var Loading = {}
var showLoad = false
var loadNode = {}
Loading.install = function (Vue, options) {
  Vue.prototype.$loading = function (type) {
    if (type === `close`) {
      loadNode.show = showLoad = false
      document.querySelector(`.loadEffect`).remove()
    } else {
      if (showLoad) {
        return
      }
      let LoadingTpl = Vue.extend({
        data: function () {
          return {
            show: showLoad
          }
        },
        template: `<div class="loadEffect"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><p class="loadings">loading....</p></div>
        `
      })
      let tpl = new LoadingTpl().$mount().$el
      document.body.appendChild(tpl)
      loadNode.show = showLoad = true;
      [`open`, `close`].forEach(function (type) {
        Vue.prototype.$loading[type] = function () {
          return Vue.prototype.$loading(type)
        }
      })
    }
  }
}

export default Loading

然後在我們的元件中使用this.$loading來使用,發現沒有任何問題。。。。。

但是。。。嘿嘿,總有但是,,沒錯下面的場景就是萬惡的但是。。。。

因為我們發現我們編寫的這個外掛只能在vue元件中使用,如果我想在axios的攔截器中使用這個外掛呢?顯然用不了,這是為什麼呢?是因為我們在axios中沒有訪問到vue的例項,因為我們的外掛是過載在vue的例項上的

現在怎麼辦,百度看了很多別人寫的部落格,不出意外,對就是那個不出意外,沒有找到合適的解決方案!!!!!!!!!!!!!!!!!

怎麼辦呢?放棄?不可能,這輩子是不可能放棄的!!!下輩子也不可能的!!!那怎麼辦?嘿嘿,世面上還是有很多牛叉的UI庫的比如element-ui,然後自己去試了一下,發現element-ui不僅在vue元件中可以使用,也可以在axios的攔截器這中呼叫

既然發現了,那就去檢視他們的原始碼,看看大佬們是如何實現的,不看不知道,一看嚇一跳,老大的程式碼果然性感,下面貼出我自己刪減後實現這個功能的核心程式碼

const Message = function (options) {
  options = options || {}
  options = {
    message: options.message,
    name: options.name,
    state: options.state
  }
  instance = new MessageConstructor({
    data: options
  })
  instance.vm = instance.$mount()
  document.body.appendChild(instance.vm.$el)
}
Vue.prototype.$message = Message

下面貼出原始碼地址

https://github.com/songdongdo…

如果對您有幫助請不要吝嗇您的start
我的原文部落格地址:http://www.cnblogs.com/songdo…

相關文章