摘要:
上班摸鱼时间瞅了一眼 app.use() 的源码实现,随手写了一段理解,不保真,感兴趣随便看看。
源码
ts
// 应用api use,使用各种plugin
use(plugin: Plugin, ...options: any[]) {
if (installedPlugins.has(plugin)) {
__DEV__ && warn(`Plugin has already been applied to target app.`)
} else if (plugin && isFunction(plugin.install)) {
installedPlugins.add(plugin)
plugin.install(app, ...options)
} else if (isFunction(plugin)) {
installedPlugins.add(plugin)
plugin(app, ...options)
} else if (__DEV__) {
warn(
`A plugin must either be a function or an object with an "install" ` +
`function.`
)
}
return app
},
实现原理
插件的 install
方法包括一个 app
参数.
如:
ts
export default const plugin = {
install (app, options) {
app.config.globalProperties.$tracker = tracker
app.config.errorHandler = () => {
....
}
}
}
在执行 app.use(plugin)
时,相当于将应用实例化的 app
作为传入 install
的第一个参数,对应用内的 app
执行一遍 install
方法中的操作。
以下是一个应用内创建 Vue 应用的代码:
ts
import { createApp } from 'vue'
import App from './App.vue'
import plugin from './plugin'
const app = createApp(App)
app.use(plugin)
app.mount('#app')
这段代码的作用,与下面一段代码一致:
ts
import { createApp } from 'vue'
import App from './App.vue'
import plugin from './plugin'
import tracker from './tracker'
const app = createApp(App)
// app.use(plugin)
app.config.globalProperties.$tracker = tracker
app.config.errorHandler = () => {
....
}
app.mount('#app')
简单来说,app.use()方法,就是把插件中对 install
方法的第一个参数(app) 做的事添加到你的应用中创建的 app
实例上。
所以,看似神秘的 App.use()
方法,实则只是给代码的组织和扩展提供了一种 简洁 和 优雅 的实现方案,本质,还是对 app
实例进行的一些操作。
当然, App.use()
方法还包括一些防止重复注册的额外操作,但不是核心功能。
需要注意
本质上 app.use()
还是利用的 app
实例是引用类型这一点实现的,所以,在写插件时,千万不要对插件的 install(app, options)
方法的 app
参数用深拷贝,深拷贝后这个插件就废了。