字 數:3781, 閱讀時間:14分鐘, 閱讀原文vue
咱們在使用Vue作項目開發的時候,看到很多輪子都是經過Vue.use
來進行使用,感受甚是高大上。 不過Vue.use
究竟是什麼鬼?不妨來看個究竟。node
其實這些輪子均可以稱之爲插件,它的功能範圍沒有嚴格的限制,通常包含以下幾種:git
vue-custom-element
vue-touch
vue-router
Vue
實例方法,經過把它們添加到 Vue.prototype
上實現。vue-router
不管大小,插件要實現的功能無非就是上述這幾種。可是,這並不妨礙咱們創造出複雜的插件,不過咱們仍是但願給用戶提供一個簡單的使用方法,他不須要關注插件內部作了些什麼。固Vue提供了use方法,專門來在new Vue()
以前使用插件。github
不論是官方提供的插件(例如vue-router
、vuex
),仍是第三方的插件(例如ElementUI
、ant
)都是採用了此方式,不外乎插件內部的功能不一樣而已。固然,還有其餘諸多此類插件,awesome-vue 就集合了大量由社區貢獻的插件和庫。vue-router
接下來,咱們就來看下這個神祕的use
方法是如何實現的。vuex
Vue.js
的插件應該暴露一個 install
方法。這個方法的第一個參數是 Vue
構造器,第二個參數是一個可選的選項對象,用於傳入插件的配置:app
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,
Dialog,
Autocomplete,
// ...other components
};
複製代碼
咱們不難發現,其實本身來實現一個插件也是超級簡單,只要對外暴露一個install
方法便可,在使用Vue.use
的時候,會調用這個方法。因此咱們只要將要實現的內容放到install
內部便可。這樣的好處就是插件須要一開始調用的方法都封裝在install
裏面,更加精簡和可拓展性更高。post
你們可能也有注意到,這裏的install
實際上是將全部的組件所有引入了。做爲一個龐大的插件庫,這樣可能會有一些性能問題。用過的ElementUI
的同窗都知道,它是支持按需引入的,其實在上面的示例中也能夠發現一些蛛絲馬跡。性能
const components = [ Pagination, Dialog, Autocomplete/* 此處因爲篇幅省略若干個組件 */];
// ....省去中間內容
export default {
version: '2.13.0',
locale: locale.use,
i18n: locale.i18n,
install,
CollapseTransition,
Loading,
Pagination,
Dialog,
Autocomplete,
// ...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
其實並不神祕,內部仍是咱們平時使用的這些東西,僅僅只是給他們套上了一層高端的外衣而已。咱們在開發中,也能夠嘗試使用這種方式,不只簡單,並且有逼格🚀🚀