淺談vue.use()方法從源碼到使用
關(guān)于 vue.use 我們都知道些什么?
在做 vue 開(kāi)發(fā)的時(shí)候大家一定經(jīng)常接觸 Vue.use() 方法,官網(wǎng)給出的解釋是: 通過(guò)全局方法 Vue.use() 使用插件;我覺(jué)得把使用理解成注冊(cè)更合適一些,首先看下面常見(jiàn)的注冊(cè)場(chǎng)景。
import Router from 'vue-router' Vue.use(Router) import Vuex from 'vuex' Vue.use(Vuex) import Echarts from 'echarts' Vue.prototype.$echarts = Echarts
關(guān)于 echarts 的注冊(cè)很簡(jiǎn)單,直接掛在 Vue 方法的原型上,通過(guò)原型鏈繼承的關(guān)系可以在任意一個(gè)組件里通過(guò) this.$echarts 訪問(wèn)到 echarts 實(shí)例,我們來(lái)寫一個(gè)簡(jiǎn)單的例子證明一下。
function myVue(title){ this.title = title } myVue.prototype.myUse = '在原型上添加公共屬性' const A = new myVue('我是實(shí)例A') const B = new myVue('我是實(shí)例B') console.log(A.title, B.title, A.myVue, B.myVue, ) // 我是實(shí)例A 我是實(shí)例B 在原型上添加公共屬性 在原型上添加公共屬性
而 Router 和 Vuex 的注冊(cè)就要去分析 Vue.use() 的源碼了,在分析源碼之前先總結(jié)一下官方對(duì) Vue.use() 方法的說(shuō)明:
- 通過(guò)全局方法 Vue.use() 使用插件
- Vue.use 會(huì)自動(dòng)阻止多次注冊(cè)相同插件
- 它需要在你調(diào)用 new Vue() 啟動(dòng)應(yīng)用之前完成
- Vue.use() 方法至少傳入一個(gè)參數(shù),該參數(shù)類型必須是 Object 或 Function,如果是 Object 那么這個(gè) Object 需要定義一個(gè) install 方法,如果是 Function 那么這個(gè)函數(shù)就被當(dāng)做 install 方法。在 Vue.use() 執(zhí)行時(shí) install 會(huì)默認(rèn)執(zhí)行,當(dāng) install 執(zhí)行時(shí)第一個(gè)參數(shù)就是 Vue,其他參數(shù)是 Vue.use() 執(zhí)行時(shí)傳入的其他參數(shù)。
官網(wǎng)說(shuō) Vue.use() 是用來(lái)使用插件的,那么傳入的 Router 和 Vuex 就是這里指的插件,而這個(gè)插件本質(zhì)上又是一個(gè) install 方法。至于 install 方法內(nèi)部實(shí)現(xiàn)了什么邏輯就由插件自身的業(yè)務(wù)決定了。
源碼分析
首先說(shuō)一下 Flow,vue源碼中那些奇怪的寫法 Vue.use = function (plugin: Function | Object) 是 Flow 的語(yǔ)法,F(xiàn)low 是 facebook 出品的 JavaScript 靜態(tài)類型檢查工具。JavaScript 是動(dòng)態(tài)類型語(yǔ)言,它的靈活性有目共睹,但是過(guò)于靈活的副作用是很容易就寫出非常隱蔽的隱患代碼,在編譯期甚至看上去都不會(huì)報(bào)錯(cuò),但在運(yùn)行階段就可能出現(xiàn)各種奇怪的 bug。
下面我們正式開(kāi)始分析源碼,Vue.use() 的源碼很簡(jiǎn)單30行都不到,首先看 src/core/global-api/use.js 下 Vue.use() 方法的定義:
import { toArray } from '../util/index' export function initUse (Vue: GlobalAPI) { Vue.use = function (plugin: Function | Object) { const installedPlugins = (this._installedPlugins || (this._installedPlugins = [])) if (installedPlugins.indexOf(plugin) > -1) { return this } const args = toArray(arguments, 1) args.unshift(this) if (typeof plugin.install === 'function') { plugin.install.apply(plugin, args) } else if (typeof plugin === 'function') { plugin.apply(null, args) } installedPlugins.push(plugin) return this } }
上面源碼中使用了工具函數(shù) toArray ,該函數(shù)定義在 src/shared/util.js
export function toArray (list: any, start?: number): Array<any> { start = start || 0 let i = list.length - start const ret: Array<any> = new Array(i) while (i--) { ret[i] = list[i + start] } return ret }
了解一下源碼實(shí)現(xiàn)了什么邏輯
Vue.use = function (plugin: Function | Object) {
在全局api Vue 上定義了 use 方法,接收一個(gè) plugin 參數(shù)可以是 Function 也可以是 Object,這就和前面官方規(guī)定的 Vue.use() 第一個(gè)參數(shù)要求的類型對(duì)應(yīng)上了。
if (installedPlugins.indexOf(plugin) > -1) {
用來(lái)判斷該插件是不是已經(jīng)注冊(cè)過(guò),防止重復(fù)注冊(cè)。
const args = toArray(arguments, 1)
arguments是 Vue.use() 方法的參數(shù)列表是一個(gè)類數(shù)組,后面的 1 先理解成一個(gè)常量,toArray 方法的作用就是把第一個(gè) Array 參數(shù)從下標(biāo)為1截取到最后。也就拿到了 Vue.use() 方法除去第一個(gè)之外的其他參數(shù),這些參數(shù)準(zhǔn)備在調(diào)用 instll 方法的時(shí)候傳入。
if (typeof plugin.install === 'function') {
} else if (typeof plugin === 'function') {
這里的if語(yǔ)句是判斷 Vue.use() 傳入的第一個(gè)參數(shù)是 Object 還是 Function。
plugin.install.apply(plugin, args)
plugin.apply(null, args)
判斷完之后執(zhí)行那個(gè)對(duì)應(yīng)的 install 方法,用 apply 改變 this 指向,并把 toArray 得到的剩余參數(shù)傳入。
installedPlugins.push(plugin)
最后記錄該組件已經(jīng)注冊(cè)過(guò)了
現(xiàn)在我們發(fā)現(xiàn) Vue.use() 的注冊(cè)本質(zhì)上就是執(zhí)行了一個(gè) install 方法,install 里的內(nèi)容由開(kāi)發(fā)者自己定義,通俗講就是一個(gè)鉤子可能更貼近語(yǔ)義化而已。
Vue.use()有什么用
在 install 里我們可以拿到 Vue 那么和 Vue 相關(guān)的周邊工作都可以考慮放在 Vue.use() 方法里,比如:
- directive注冊(cè)
- mixin注冊(cè)
- filters注冊(cè)
- components注冊(cè)
- prototype掛載
- ...
echarts 用 Vue.use() 來(lái)注冊(cè)
main.js
import Vue from 'vue' import echarts from './echarts.js' Vue.use(echarts) new Vue({ ... })
echarts.js
import Echarts from 'echarts' export default { install(Vue){ Vue.prototype.$echarts = Echarts } }
這樣寫的好處是可以在 install 的文件里做更多配置相關(guān)的工作,main.js 不會(huì)變的臃腫,更方便管理。
全局組件用 Vue.use() 來(lái)注冊(cè)
base.js
import a from './a' import b from './b' let components = { a, b } const installBase = { install (Vue) { Object.keys(components).map(key => Vue.component(key, components[key])) } }
main.js
import Vue from 'vue' import base from './base.js' Vue.use(base) new Vue({ ... })
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
說(shuō)說(shuō)Vuex的getters屬性的具體用法
這篇文章主要介紹了說(shuō)說(shuō)Vuex的getters屬性的具體用法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-04-04vue中el-table單元格復(fù)制功能實(shí)現(xiàn)
這篇文章主要介紹了vue中el-table單元格復(fù)制功能實(shí)現(xiàn),本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-07-07vue使用echarts詞云圖的實(shí)戰(zhàn)記錄
這篇文章主要給大家介紹了關(guān)于vue使用echarts詞云圖的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05vue中vue-router的使用說(shuō)明(包括在ssr中的使用)
這篇文章主要介紹了vue中vue-router的使用說(shuō)明(包括在ssr中的使用),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05vue使用less報(bào)錯(cuò):Inline JavaScript is not ena
這篇文章主要介紹了vue使用less報(bào)錯(cuò):Inline JavaScript is not enabled問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01elementui導(dǎo)出數(shù)據(jù)為xlsx、excel表格
本文主要介紹了elementui導(dǎo)出數(shù)據(jù)為xlsx、excel表格,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09Element修改彈窗類組件的層級(jí)的實(shí)現(xiàn)
本文主要介紹了Element修改彈窗類組件的層級(jí)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04