Vue3设置全局变量的四种方法
在vue3项目中,我们经常需要在多个组件之间共享数据。比如用户登录信息、应用主题设置、api地址等。这些数据如果每个组件都单独管理,会很麻烦。下面介绍四种设置全局变量的方法,你可以根据项目需求选择合适的方式。
1. 使用 app.config.globalProperties
这是Vue3官方提供的一种方法。你可以把变量或方法挂载到Vue应用的全局实例上,然后在任何组件中通过 this 访问。
具体做法
在 main.js 或 main.ts 文件中设置:
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 定义全局数据
const globalData = {
apiBaseUrl: 'https://api.yoursite.com/v1',
siteName: '我的Vue应用',
showToast(message) {
// 显示提示框的逻辑
console.log('Toast:', message)
}
}
// 挂载到全局属性
app.config.globalProperties.$global = globalData
app.mount('#app')在组件中使用:
<template>
<div>
<h1>欢迎来到 {{ $global.siteName }}</h1>
<button @click="fetchData">获取数据</button>
</div>
</template>
<script>
export default {
methods: {
fetchData() {
const url = this.$global.apiBaseUrl + '/user'
console.log('请求地址:', url)
this.$global.showToast('开始获取数据')
}
}
}
</script>注意事项
如果你使用TypeScript,需要在类型声明文件中添加:
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$global: {
apiBaseUrl: string;
siteName: string;
showToast: (msg: string) => void;
}
}
}在 <script setup> 语法中,需要使用 getCurrentInstance:
<script setup>
import { getCurrentInstance } from 'vue'
const instance = getCurrentInstance()
const globalData = instance?.appContext.config.globalProperties.$global
const handleClick = () => {
globalData?.showToast('来自setup的消息')
}
</script>适用场景:适合从Vue2升级的项目,或者在选项式API中使用。
2. 使用依赖注入(Provide / Inject)
这是Vue3推荐的方式,特别适合组合式API。在应用顶层提供数据,在子组件中注入使用。
具体做法
在 main.js 中提供数据:
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
const globalData = {
apiBaseUrl: 'https://api.yoursite.com/v1',
siteName: '我的Vue应用',
}
// 提供全局数据
app.provide('globalData', globalData)
app.mount('#app')在子组件中注入使用:
<template>
<div>
<p>网站名称:{{ siteName }}</p>
<button @click="testApi">测试API地址</button>
</div>
</template>
<script setup>
import { inject } from 'vue'
// 注入全局数据
const globalData = inject('globalData')
const siteName = globalData.siteName
const testApi = () => {
console.log('API基础地址是:', globalData.apiBaseUrl)
}
</script>响应式数据示例
你可以提供响应式数据,这样所有使用该数据的组件都会同步更新:
import { createApp, reactive } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 创建响应式全局状态
const globalState = reactive({
user: {
name: '访客',
isLogin: false
},
theme: 'light'
})
// 提供修改状态的方法
function login(userInfo) {
globalState.user.name = userInfo.name
globalState.user.isLogin = true
}
app.provide('globalState', globalState)
app.provide('login', login)
app.mount('#app')适用场景:适合组合式API项目,需要响应式数据的场景。
3. 使用状态管理(Pinia)
Pinia是Vue3官方推荐的状态管理库。它适合管理复杂的全局状态,功能强大且支持TypeScript。
具体做法
首先安装Pinia:
npm install pinia在 main.js 中设置:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.mount('#app')创建状态仓库:
// src/stores/global.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useGlobalStore = defineStore('global', () => {
// 状态
const siteName = ref('我的Vue应用')
const apiBaseUrl = ref('https://api.yoursite.com/v1')
const user = ref({ name: '访客', isLogin: false })
const theme = ref('light')
// 计算属性
const welcomeMessage = computed(() => {
return user.value.isLogin ? `欢迎回来,${user.value.name}` : '请先登录'
})
// 方法
function login(userInfo) {
user.value.name = userInfo.name
user.value.isLogin = true
}
function logout() {
user.value.name = '访客'
user.value.isLogin = false
}
function toggleTheme() {
theme.value = theme.value === 'light' ? 'dark' : 'light'
}
return {
siteName,
apiBaseUrl,
user,
theme,
welcomeMessage,
login,
logout,
toggleTheme
}
})在组件中使用:
<template>
<div :class="`app-${globalStore.theme}`">
<h1>{{ globalStore.siteName }}</h1>
<p>{{ globalStore.welcomeMessage }}</p>
<button @click="handleLogin">登录</button>
<button @click="globalStore.toggleTheme">切换主题</button>
</div>
</template>
<script setup>
import { useGlobalStore } from '@/stores/global'
const globalStore = useGlobalStore()
const handleLogin = () => {
globalStore.login({ name: '李四' })
}
</script>适用场景:中大型项目,需要管理复杂状态的情况。
4. 使用纯JavaScript模块
如果只是需要共享一些不会变化的配置或工具函数,一个简单的JavaScript模块就足够了。
具体做法
创建配置文件:
// src/config/constants.js
export const API_BASE_URL = 'https://api.yoursite.com/v1'
export const SITE_NAME = '我的Vue应用'
export const APP_VERSION = '1.0.0'
export const MAX_UPLOAD_SIZE = 5 * 1024 * 1024 // 5MB
// 工具函数
export function formatDate(date) {
return new Date(date).toLocaleDateString()
}
export function formatPrice(price) {
return '¥' + price.toFixed(2)
}在组件中导入使用:
<script setup>
import { API_BASE_URL, SITE_NAME, formatDate } from '@/config/constants'
console.log(`正在访问 ${SITE_NAME},API地址:${API_BASE_URL}`)
const today = formatDate(new Date())
</script>适用场景:静态配置、工具函数等不会变化的数据。
如何选择合适的方法
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| app.config.globalProperties | Vue2升级项目,选项式API | 简单直接,类似Vue2写法 | 组合式API中使用不便 |
| Provide / Inject | 组合式API,响应式数据共享 | 官方推荐,响应式支持好 | 数据流向是单向的 |
| Pinia | 中大型项目,复杂状态管理 | 功能强大,TypeScript支持好 | 需要学习额外概念 |
| JavaScript模块 | 静态配置,工具函数 | 最简单,零依赖,性能好 | 不支持响应式 |
实际应用建议
小型项目:如果只是共享几个配置项,用JavaScript模块最方便。
中型项目:需要响应式数据共享,使用Provide / Inject。
大型项目:状态复杂,需要严格管理,使用Pinia。
Vue2迁移项目:习惯使用this访问全局数据,可以用app.config.globalProperties。
记住,选择哪种方法要看具体需求。不要为了用而用,简单有效才是最重要的。先从小处开始,随着项目发展再调整方案。
常见问题解答
Q:哪种方法性能最好?
A:JavaScript模块性能最好,因为它没有响应式系统的开销。
Q:Pinia和Vuex有什么区别?
A:Pinia是Vue3的官方推荐,API更简洁,TypeScript支持更好,学习成本更低。
Q:全局变量太多怎么办?
A:按功能拆分。用户相关的放一起,配置相关的放一起,不要全部堆在一个地方。
Q:响应式数据会影响性能吗?
A:会有一点影响,但现代浏览器处理能力很强,一般不用担心。只有数据量很大时才需要考虑优化。
掌握这四种方法,你就能应对Vue3项目中各种全局数据共享的需求了。根据项目实际情况选择合适的方法,让代码更清晰,更易维护。
本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!