在Vue中,挂载全局方法通常是为了在整个应用中的任何组件都可以使用这些方法。Vue2和Vue3在挂载全局方法上有所不同,主要因为Vue3引入了新的应用实例概念。
在Vue2中,我们通常通过修改Vue的原型(prototype)来实现全局方法的挂载。这样在每个Vue组件实例中都可以通过`this`来访问这些方法。
在Vue3中,我们不再使用`Vue.prototype`,而是通过app实例的`config.globalProperties`来添加全局方法。另外,Vue3推荐使用provide/inject来实现全局状态或方法,但对于方法,使用`globalProperties`更为直接。
Vue 2 挂载全局方法(3种方式)
1. 通过 Vue.prototype
挂载 (最常用)
// main.js
import Vue from 'vue'
// 定义全局方法
const globalMethod = {
showToast(message) {
console.log(`Toast: ${message}`)
// 实际项目中这里实现toast逻辑
},
formatCurrency(value) {
return `¥${parseFloat(value).toFixed(2)}`
}
}
// 挂载到Vue原型
Vue.prototype.$utils = globalMethod
// 使用示例(在组件中)
export default {
mounted() {
this.$utils.showToast('操作成功!') // Toast: 操作成功!
const price = this.$utils.formatCurrency(99.8) // ¥99.80
}
}
2. 使用 Mixin 全局混入
// main.js
import Vue from 'vue'
Vue.mixin({
methods: {
$logInfo(message) {
console.log(`[INFO] ${new Date().toISOString()}: ${message}`)
},
$copyText(text) {
navigator.clipboard.writeText(text)
}
}
})
// 组件中使用
this.$logInfo('页面加载完成') // [INFO] 2023-08-01T10:00:00.000Z: 页面加载完成
this.$copyText('复制内容')
3. 作为插件安装
// utilsPlugin.js
export default {
install(Vue) {
Vue.prototype.$api = {
fetchData(url) {
return fetch(url).then(res => res.json())
},
debounce(fn, delay = 300) {
let timer = null
return (...args) => {
clearTimeout(timer)
timer = setTimeout(() => fn.apply(this, args), delay)
}
}
}
}
}
// main.js
import Vue from 'vue'
import utilsPlugin from './plugins/utilsPlugin'
Vue.use(utilsPlugin)
// 组件中使用
this.$api.fetchData('/api/data').then(data => { /*...*/ })
const debouncedSearch = this.$api.debounce(this.handleSearch, 500)
Vue 3 挂载全局方法(Composition API)
1. 通过 app.config.globalProperties
挂载 (推荐)
// main.js
import { createApp } from 'vue'
const app = createApp(App)
// 定义全局方法
const globalMethods = {
$showLoading() {
// 显示加载动画
},
$hideLoading() {
// 隐藏加载动画
},
$formatDate(date, format = 'YYYY-MM-DD') {
return dayjs(date).format(format)
}
}
// 挂载全局属性
app.config.globalProperties.$utils = globalMethods
app.mount('#app')
// 组件中使用(Options API)
export default {
mounted() {
this.$utils.$showLoading()
const date = this.$utils.$formatDate(new Date())
}
}
// 组合式API中使用
import { getCurrentInstance } from 'vue'
export default {
setup() {
const { proxy } = getCurrentInstance()
const handleSubmit = () => {
proxy.$utils.$showLoading()
// ...
proxy.$utils.$hideLoading()
}
return { handleSubmit }
}
}
2. 使用 provide/inject (更适合全局工具)
// main.js
import { createApp } from 'vue'
const app = createApp(App)
// 创建工具集
const globalUtils = {
trackEvent(eventName) {
// 埋点统计
},
deepClone(obj) {
return JSON.parse(JSON.stringify(obj))
}
}
// 提供全局工具
app.provide('globalUtils', globalUtils)
// 组件中使用
import { inject } from 'vue'
export default {
setup() {
const utils = inject('globalUtils')
const handleClick = () => {
utils.trackEvent('button_click')
const clonedObj = utils.deepClone(originalObj)
}
return { handleClick }
}
}
3. 作为插件安装 (最佳实践)
// globalUtils.js
export default {
install(app) {
// 挂载全局方法
app.config.globalProperties.$alert = (message) => {
// 实现alert逻辑
}
// 注册全局组件
app.component('GlobalSpinner', SpinnerComponent)
// 提供响应式工具
const utils = reactive({
screenSize: { width: window.innerWidth, height: window.innerHeight },
isMobile: window.innerWidth < 768
})
// 监听窗口变化
window.addEventListener('resize', () => {
utils.screenSize = {
width: window.innerWidth,
height: window.innerHeight
}
utils.isMobile = window.innerWidth < 768
})
app.provide('responsiveUtils', utils)
}
}
// main.js
import { createApp } from 'vue'
import globalUtils from './plugins/globalUtils'
createApp(App)
.use(globalUtils)
.mount('#app')
// 组件中使用
export default {
mounted() {
this.$alert('操作成功!') // 全局方法
},
setup() {
const { isMobile } = inject('responsiveUtils')
return { isMobile }
}
}
关键区别总结
特性 | Vue 2 | Vue 3 |
---|---|---|
主要挂载方式 | Vue.prototype | app.config.globalProperties |
插件安装 | Vue.use(plugin) | app.use(plugin) |
Composition API | 不支持 | getCurrentInstance().proxy 或 inject |
类型支持 | 有限 | 完善的TypeScript支持 |
全局状态管理 | 需配合Vuex | 可通过provide/inject实现 |
响应式工具 | 需手动实现 | 可集成reactive/ref响应式系统 |
注意:在Vue3的组合式API中,由于`setup`函数中无法直接访问`this`,因此需要通过`getCurrentInstance`来获取代理对象。但是,官方文档指出,`getCurrentInstance`主要作为内部使用,在库中谨慎使用。因此,在组合式API中,更推荐使用模块导入的方式或者使用provide/inject来传递方法。