Vue.use(plugin)詳解

閱讀此文章,你可以了解到:

Vue.use(plugin)基礎概念(什么是Vue.use(plugin))

Vue.use的簡單使用

為什么在引入Vue-Router、ElementUI的時候需要Vue.use()?而引入axios的時候,不需要Vue.use()?

Vue-Router、ElementUI在Vue.use()分別做了什么?

Vue.use原理

如何編寫一個Vue插件?

什么是Vue.use(plugin)

Vue.use是用來安裝插件的。

用法

Vue.use(plugin)

如果插件是一個對象,必須提供install方法。

如果插件是一個函數,它會被作為 install 方法。install 方法調用時,會將 Vue 作為參數傳入。

Vue.use(plugin)調用之后,插件的install方法就會默認接受到一個參數,這個參數就是Vue(原理部分會將)

該方法需要在調用new Vue()之前被調用。

當 install 方法被同一個插件多次調用,插件將只會被安裝一次。(源碼解析的時候會解析如何實現)

總結:Vue.use是官方提供給開發者的一個api,用來注冊、安裝類型Vuex、vue-router、ElementUI之類的插件的。

Vue.use的簡單使用

看一下具體的例子:

我們在用Vue-cli3.0里面初始化項目的時候,會生成一個入口文件main.js

在main.js中,如何我們安裝了Vue-Router、Vuex、ElementUI,并且想要在項目中使用,就得在入口文件main.js中調用一下Vue.use()

Vue.use(ElementUi);Vue.use(Vuex);Vue.use(Router);復制代碼

這樣就算是完成了對三個插件的安裝,我們就可以在組件中調用this.$router、this.$route、this.$store、this.$alert()(ElementUI的彈窗組件)參數(方法)。

為什么在引入Vue-Router、Vuex、ElementUI的時候需要Vue.use()?而引入axios的時候,不需要Vue.use()?

我們在講什么是Vue.use的時候,已經說明要用use安裝的插件,要么是一個對象里面包含install方法,要么本身就是一個方法(自身就是install方法)。

也就是說,這個題目的答案,本質就是:Vue-Router、Vuex、ElementUI三者都具有install方法,并且插件的運行依賴于install方法里的一些操作,才能正常運行,而axios沒有install方法也能正常運行。

看到這里你一定會疑惑:

同樣是插件,為什么有些插件要有install方法才能正常運行(如VueRouter),有一些卻可以沒有install方法也可以使用(如axios)?

插件的install方法,可以為我們做什么?

Vue-Router、ElementUI在install里面到底做了什么?

在探究這個問題之前,我們先看看Vue.use這個方法到底做了什么。

Vue中的use原理

exportfunctioninitUse(Vue: GlobalAPI){? Vue.use =function(plugin: Function | Object){// 獲取已經安裝的插件constinstalledPlugins = (this._installedPlugins || (this._installedPlugins = []))// 看看插件是否已經安裝,如果安裝了直接返回if(installedPlugins.indexOf(plugin) >-1) {returnthis}// toArray(arguments, 1)實現的功能就是,獲取Vue.use(plugin,xx,xx)中的其他參數。// 比如 Vue.use(plugin,{size:'mini', theme:'black'}),就會回去到plugin意外的參數constargs = toArray(arguments,1)// 在參數中第一位插入Vue,從而保證第一個參數是Vue實例args.unshift(this)// 插件要么是一個函數,要么是一個對象(對象包含install方法)if(typeofplugin.install ==='function') {// 調用插件的install方法,并傳入Vue實例plugin.install.apply(plugin, args)? ? }elseif(typeofplugin ==='function') {? ? ? plugin.apply(null, args)? ? }// 在已經安裝的插件數組中,放進去installedPlugins.push(plugin)returnthis}}復制代碼

總結:

Vue.use方法主要做了如下的事:

檢查插件是否安裝,如果安裝了就不再安裝

如果沒有沒有安裝,那么調用插件的install方法,并傳入Vue實例

我們知道了Vue.use做了什么之后。我們看看那些我們常見的插件,是如何利用這個use方法的。

Element中的install

constinstall =function(Vue, opts = {}){? locale.use(opts.locale);? locale.i18n(opts.i18n);// components是ElementUI的組件數組,里面有Dialog、Input之類的組件// 往Vue上面掛載組件components.forEach(component=>{? ? Vue.component(component.name, component);? });? Vue.use(Loading.directive);// 自定義一些參數Vue.prototype.$ELEMENT = {size: opts.size ||'',zIndex: opts.zIndex ||2000};// 在Vue原型上注冊一些方法,這就是為什么我們可以直接使用this.$alert、this.$loading的原因,值就是這么來的。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;};復制代碼

同樣的方法,我們來看看Vue-Router的install又做了什么。

Vue-Router中的install

我們先把這個install方法的部分拆解出來,只關注其最最核心的邏輯

如果不想讀源碼,可以直接看源碼后面的文字簡單總結

importViewfrom'./components/view'importLinkfrom'./components/link'exportlet_Vueexportfunctioninstall(Vue){? _Vue = VueconstisDef =v=>v !==undefinedconstregisterInstance =(vm, callVal) =>{leti = vm.$options._parentVnodeif(isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {? ? ? i(vm, callVal)? ? }? }? Vue.mixin({? ? beforeCreate () {// 如果該組件是根組件if(isDef(this.$options.router)) {//? 設置根組件叫_routerRootthis._routerRoot =this// 根組件的_router屬性為,new Vue傳進去的router// $options是在mains.js中,new Vue里的參數,在這里我們傳入的參數,this._router =this.$options.routerthis._router.init(this)// 通過defineReactive方法,來把this._router.history.current變成響應式的,這個方法的底層就是object.definePropertyVue.util.defineReactive(this,'_route',this._router.history.current)? ? ? }else{// 如果該組件不是根組件,那么遞歸往上找,知道找到根組件的。// 因為Vue渲染組件是先渲染根組件,然后渲染根組件的子組件啊,然后再渲染孫子組件。// 結果就是每一個組件都有this._routerRoot屬性,該屬性指向了根組件。this._routerRoot = (this.$parent &&this.$parent._routerRoot) ||this}? ? ? registerInstance(this,this)? ? },? ? destroyed () {? ? ? registerInstance(this)? ? }? })// 把自身$router代理為this._routerRoot(根組件的)的_router// 根組件的_router,就是new Vue傳入的 router// 這樣就實現了,每一個Vue組件都有$router、$route屬性Object.defineProperty(Vue.prototype,'$router', {? ? get () {returnthis._routerRoot._router }? })// 同理,這樣就是把自身的$route,代理到根組件傳入的routeObject.defineProperty(Vue.prototype,'$route', {? ? get () {returnthis._routerRoot._route }? })// 注冊 <router-view>組件Vue.component('RouterView', View)// 注冊<router-link>組件Vue.component('RouterLink', Link)conststrats = Vue.config.optionMergeStrategies// use the same hook merging strategy for route hooksstrats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created}復制代碼

總結:vue-router的install方法主要幫我們做了如下事情:

通過minxi混入的方式,如果自身是根組件,就把根組件的_router屬性映射為new Vue傳入的router實例(this.$options.router)。

如果自身不是根組件,那么層層往上找,直到找到根組件,并用_routerRoot標記出根組件

為每一個組件代理$router、$route屬性,這樣每一個組件都可以去到$router、$route

注冊<router-link>、<router-view>組件

看到這里,你應該明白了,為什么vueRouter需要install才能使用了吧。

底層一點的理由就是,vueRouter需要在install方法,對Vue實例做一些自定義化的操作:比如在vue.prototype中添加$router、$route屬性、注冊<router-link>組件

為什么axios不需要安裝,可以開箱即用?

其實理由也很簡單,跟上面需要install的相反的。因為axios是基于Promise封裝的庫,是完全獨立于Vue的,根本不需要掛載在Vue上也能實現發送請求。

而因為VueRouter需要為我們提供$router、$routers之類的屬性,要依賴與Vue或者操作Vue實例才能實現。

Vue.use實際上就是Vue實例與插件的一座橋梁。

來源鏈接:https://juejin.cn/post/6844903946343940104

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,480評論 2 379

推薦閱讀更多精彩內容

  • 一.Vue-CLI基本使用 什么是Vue-CLI (Command Line Interface)?Vue -CL...
    Angel_6c4e閱讀 1,264評論 0 5
  • Vue.use到底是什么鬼?下面本篇文章就來給大家介紹一下Vue.use。有一定的參考價值,有需要的朋友可以參考一...
    淺淺而談閱讀 903評論 0 3
  • 一,基本用法 插件通常為 Vue 來添加全局功能。而插件的應用范圍沒有明確規定,一般包括:添加全局方法或屬性。例如...
    Alaricming閱讀 4,414評論 0 2
  • 前言 隨著 Vue.js 越來越火,Vue.js 的相關插件也在不斷的被貢獻出來,數不勝數。比如官方推薦的 vue...
    仰望_IT閱讀 1,127評論 0 1
  • 一、概念介紹 Vue.js和React.js分別是目前國內和國外最火的前端框架,框架跟類庫/插件不同,框架是一套完...
    劉遠舟閱讀 1,080評論 0 0