1. 程式人生 > 程式設計 >淺談Vue.use到底是什麼鬼

淺談Vue.use到底是什麼鬼

我們在使用Vue做專案開發的時候,看到不少輪子都是通過Vue.use來進行使用,感覺甚是高大上。

不過Vue.use到底是什麼鬼?不妨來看個究竟。

其實這些輪子都可以稱之為外掛,它的功能範圍沒有嚴格的限制,一般包含如下幾種:

  • 新增全域性方法或者屬性。如: vue-custom-element
  • 新增全域性資源:指令/過濾器/過渡/元件等。如 vue-touch
  • 通過全域性混入來新增一些元件選項。如 vue-router
  • 新增 Vue 例項方法,通過把它們新增到 Vue.prototype 上實現。
  • 一個庫,提供自己的 API,同時提供上面提到的一個或多個功能。如 vue-router

無論大小,外掛要實現的功能無非就是上述這幾種。但是,這並不妨礙我們創造出複雜的外掛,不過我們還是希望給使用者提供一個簡單的使用方法,他不需要關注外掛內部做了些什麼。固Vue提供了use方法,專門來在new Vue()之前使用外掛。

不管是官方提供的外掛(例如vue-router、vuex),還是第三方的外掛(例如ElementUI、ant)都是採用了此方式,不外乎外掛內部的功能不同而已。當然,還有其他諸多此類外掛,awesome-vue 就集合了大量由社群貢獻的外掛和庫。

接下來,我們就來看下這個神祕的use方法是如何實現的。

Vue.js 的外掛應該暴露一個 install 方法。這個方法的第一個引數是 Vue 構造器,第二個引數是一個可選的選項物件,用於傳入外掛的配置:

MyPlugin.install = function (Vue,options) {
 // 1. 新增全域性方法或屬性
 Vue.myGlobalMethod = function () {
  // 邏輯...
 }
 // 2. 新增全域性資源
 Vue.directive('my-directive',{
  bind (el,binding,vnode,oldVnode) {
   // 邏輯...
  }
  ...
 })
 // 3. 注入元件選項
 Vue.mixin({
  created: function () {
   // 邏輯...
  }
  ...
 })
 // 4. 新增例項方法
 Vue.prototype.$myMethod = function (methodOptions) {
  // 邏輯...
 }
 // 5. 註冊全域性元件
 Vue.component('myButton',{
  // ...元件選項
 })
}
Vue.use(MyPlugin,{
 // ...options
})

一個外掛內部大概就是如上所示,其實也不外乎上述那幾種東西,甚是簡單😄😄。接下來我們就來看下真實的案例ElementUI:

const components = [ Pagination,Dialog,Autocomplete/* 此處由於篇幅省略若干個元件 */];
const install = function(Vue,opts = {}) {
 locale.use(opts.locale);
 locale.i18n(opts.i18n);
 // 註冊全域性元件
 components.forEach(component => {
  Vue.component(component.name,component);
 });
 Vue.use(InfiniteScroll);
 Vue.use(Loading.directive);
 // 新增例項方法
 Vue.prototype.$ELEMENT = {
  size: opts.size || '',zIndex: opts.zIndex || 2000
 };
 // 新增例項方法
 Vue.prototype.$loading = Loading.service;
 Vue.prototype.$msgbox = MessageBox;
 Vue.prototype.$alert = MessageBox.alert;
 Vue.prototype.$confirm = MessageBox.confirm;
 Vue.prototype.$prompt = MessageBox.prompt;
 Vue.prototype.$notify = Notification;
 Vue.prototype.$message = Message;
};
/* istanbul ignore if */
if (typeof window !== 'undefined' && window.Vue) {
 install(window.Vue);
}
export default {
 version: '2.13.0',locale: locale.use,i18n: locale.i18n,install,CollapseTransition,Loading,Pagination,Autocomplete,// ...other components
};

我們不難發現,其實自己來實現一個外掛也是超級簡單,只要對外暴露一個install方法即可,在使用Vue.use的時候,會呼叫這個方法。所以我們只要將要實現的內容放到install內部即可。這樣的好處就是外掛需要一開始呼叫的方法都封裝在install裡面,更加精簡和可拓展性更高。

大家可能也有注意到,這裡的install其實是將所有的元件全部引入了。作為一個龐大的外掛庫,這樣可能會有一些效能問題。用過的ElementUI的同學都知道,它是支援按需引入的,其實在上面的示例中也可以發現一些蛛絲馬跡。

const components = [ Pagination,Autocomplete/* 此處由於篇幅省略若干個元件 */];
// ....省去中間內容
export default {
 version: '2.13.0',// ...other components
};

這裡將每個元件都單獨都匯出了,而在每個元件內部,也類似的暴露了install來元件每個元件,這樣就可以單獨Vue.use每個元件,從而實現按需引入的目的。

import Alert from './src/main';
/* istanbul ignore next */
Alert.install = function(Vue) {
 Vue.component(Alert.name,Alert);
};
export default Alert;

除了上述內容之外,還有幾點值得我們注意一下:

外掛傳入的如果是一個物件,則執行其install方法,如果是一個函式,則執行它自身,並bind this為null,然後傳入額外的引數

if (typeof plugin.install === 'function') {
 plugin.install.apply(plugin,args);
} else if (typeof plugin === 'function') {
 plugin.apply(null,args);
}

如果外掛沒有被註冊過,那麼註冊成功之後會給外掛新增一個installed的屬性,其值為true。Vue.use方法內部會檢測外掛的installed屬性,從而避免重複註冊外掛

Vue.use其實並不神祕,內部還是我們平時使用的這些東西,僅僅只是給他們套上了一層高階的外衣而已。我們在開發中,也可以嘗試使用這種方式,不僅簡單,而且有逼格

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。