一、核心作用与使用场景
app.use()
是 Vue 3 应用实例的关键 API,主要用于:
- 安装 Vue 插件(Vue Router、Vuex、UI 库等)
- 注册全局功能(组件、指令、混入等)
- 配置应用级选项
- 添加全局属性/方法
二、基本使用方式
javascript
import { createApp } from 'vue'
import App from './App.vue'
import MyPlugin from './plugins/my-plugin'
const app = createApp(App)
// 基本用法
app.use(MyPlugin)
// 带配置选项
app.use(MyPlugin, {
size: 'large',
theme: 'dark'
})
app.mount('#app')
三、插件开发规范
插件可以是以下两种形式:
1. 对象形式(必须包含 install 方法)
javascript
// my-plugin.js
export default {
install: (app, options) => {
// 1. 添加全局组件
app.component('MyComponent', { /* ... */ })
// 2. 添加全局指令
app.directive('focus', {
mounted(el) {
el.focus()
}
})
// 3. 添加全局属性
app.config.globalProperties.$myMethod = () => {
console.log('Global method called')
}
// 4. 使用配置选项
console.log('Plugin options:', options)
// 5. 使用 provide/inject
app.provide('myService', { /* ... */ })
}
}
2. 函数形式(直接作为 install 方法)
javascript
// my-function-plugin.js
export default function (app, options) {
// 插件实现...
}
四、源码深度分析(基于 Vue 3.3 版本)
核心源码位置
/packages/runtime-core/src/apiCreateApp.ts
关键代码实现
typescript
// 简化后的核心实现
export function createAppAPI<HostElement>(
render: RootRenderFunction,
hydrate?: RootHydrateFunction
): CreateAppFunction<HostElement> {
return function createApp(rootComponent, rootProps = null) {
// 创建应用上下文
const context = createAppContext()
// 已安装插件集合(防止重复安装)
const installedPlugins = new Set()
const app: App = {
// ...其他应用API
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
}
}
return app
}
}
源码关键点解析:
-
插件存储机制 :使用
Set
存储已安装插件,避免重复安装typescriptconst installedPlugins = new Set()
-
插件类型检查:
typescriptif (plugin && isFunction(plugin.install)) { // 处理对象形式插件 } else if (isFunction(plugin)) { // 处理函数形式插件 }
-
错误处理:开发环境下对无效插件发出警告
typescriptwarn(`A plugin must either be a function or an object...`)
-
参数传递:支持向插件传递额外参数
typescriptplugin.install(app, ...options)
-
链式调用支持:返回应用实例本身
typescriptreturn app
五、实际应用案例
1. 自定义插件示例(带配置)
javascript
// plugins/notification.js
export default {
install(app, options = {}) {
// 合并默认配置
const finalOptions = {
position: 'top-right',
timeout: 3000,
...options
}
// 创建通知容器
const container = document.createElement('div')
container.className = `notification-container ${finalOptions.position}`
document.body.appendChild(container)
// 添加全局方法
app.config.globalProperties.$notify = (message, type = 'info') => {
const notification = document.createElement('div')
notification.className = `notification ${type}`
notification.textContent = message
container.appendChild(notification)
setTimeout(() => {
notification.remove()
}, finalOptions.timeout)
}
}
}
使用插件:
javascript
// main.js
import NotificationPlugin from './plugins/notification'
app.use(NotificationPlugin, {
position: 'bottom-left',
timeout: 5000
})
// 组件中使用
export default {
methods: {
showSuccess() {
this.$notify('操作成功!', 'success')
}
}
}
2. 组合式 API 插件
javascript
// plugins/analytics.js
export default {
install(app, { trackingId }) {
// 提供可注入服务
app.provide('analytics', {
trackEvent(eventName, payload) {
console.log(`[${trackingId}] Tracking:`, eventName, payload)
// 实际发送到分析平台...
}
})
}
}
// 组件中使用
import { inject } from 'vue'
export default {
setup() {
const analytics = inject('analytics')
const buttonClick = () => {
analytics.trackEvent('button_click', { id: 'cta-btn' })
}
return { buttonClick }
}
}
六、最佳实践与注意事项
-
安装时机 :必须在
mount()
之前调用javascript// ✅ 正确 app.use(plugin).mount('#app') // ❌ 错误 app.mount('#app') app.use(plugin) // 不会生效
-
插件设计原则:
- 避免直接修改全局对象
- 优先使用
app.provide/inject
而非全局属性 - 清理副作用(在 unmount 时)
-
插件卸载处理:
javascriptexport default { install(app) { const handler = () => { /* ... */ } window.addEventListener('resize', handler) // 注册卸载清理函数 app.mixin({ unmounted() { window.removeEventListener('resize', handler) } }) } }
-
类型安全(TypeScript):
typescript// 扩展全局属性类型声明 declare module '@vue/runtime-core' { interface ComponentCustomProperties { $notify: (msg: string, type?: 'info'|'success'|'error') => void } }
七、常见内置插件实现原理
1. Vue Router
javascript
// 简化版实现
export default {
install(app, options) {
// 注册全局组件
app.component('RouterView', RouterView)
app.component('RouterLink', RouterLink)
// 添加全局属性
app.config.globalProperties.$router = options.router
app.config.globalProperties.$route = options.router.currentRoute
// 提供路由实例
app.provide('router', options.router)
app.provide('route', options.router.currentRoute)
// 安装导航守卫
options.router.beforeEach(/* ... */)
}
}
2. Pinia
javascript
export default {
install(app, options) {
// 提供 store 实例
app.provide('pinia', options.pinia)
// 添加全局属性
if (!__VUE_OPTIONS_API__) return
app.config.globalProperties.$pinia = options.pinia
app.mixin({
beforeCreate() {
// 注入 store 到组件实例
if (this.$options.stores) {
// ...
}
}
})
}
}
八、高级技巧
1. 条件插件安装
javascript
// main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 根据环境安装插件
if (import.meta.env.VITE_ENABLE_ANALYTICS === 'true') {
import('./plugins/analytics').then(module => {
app.use(module.default, { trackingId: 'UA-XXXXX' })
app.mount('#app')
})
} else {
app.mount('#app')
}
2. 插件自动加载
javascript
// plugins/index.js
const pluginFiles = import.meta.glob('./*.js')
export default {
install(app) {
Object.values(pluginFiles).forEach(plugin => {
plugin().then(module => {
app.use(module.default)
})
})
}
}
// main.js
import Plugins from './plugins'
app.use(Plugins)
九、性能优化建议
-
按需加载:动态导入大型插件
javascriptimport('./heavy-plugin').then(plugin => { app.use(plugin.default) })
-
轻量级替代:避免安装未使用的功能
javascript// 替代整个 UI 库 import { Button, Input } from 'ui-library' app.component('UiButton', Button) app.component('UiInput', Input)
-
SSR 兼容:
javascriptexport default { install(app, options) { // 检查是否在浏览器环境 if (typeof window !== 'undefined') { // 仅客户端执行的代码 } } }
总结
app.use()
是 Vue 3 插件系统的核心:
- 机制:通过 install 方法注入应用上下文
- 实现:使用 Set 跟踪安装状态,支持对象/函数插件
- 最佳实践:优先使用 provide/inject,清理副作用
- 高级应用:支持异步加载、条件安装等场景