Vue 3 中全局属性必须在 createApp() 后、mount() 前通过 app.config.globalProperties 注册,Options API 中直接用 this.$xxx,Composition API 需通过 getCurrentInstance().proxy 访问,推荐挂载简单工具函数并统一管理。
Vue 3 中用 app.config.globalProperties 挂载全局属性,核心就一点:在应用实例创建后、挂载前完成注册,之后所有组件(Options API 或 Composition API)都能按需访问。
注册位置错误是常见问题。不能写成两次 createApp(),也不能在 mount() 之后才加——那样全局属性根本不会生效。
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 在这里挂载
app.config.globalProperties.$apiBase = 'https://api.example.com'
app.config.globalProperties.$log = (msg) => console.info('[APP]', msg)
app.mount('#app')
和 Vue 2 的 this.$xxx 用法一致,无需额外引入或解构。
<p>{{ $apiBase }}</p>
this.$log('初始化完成')
data() { return { $apiBase: 'xxx' } }),会覆盖全局的,优先取组件内部定义的。Setup 里没有 this,必须通过实例获取 proxy 才能访问全局属性。
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
console.log(proxy.$apiBase)
import { getCurrentInstance } from 'vue'
const instance = getCurrentInstance()
if (instance) {
const { appContext: { config: { globalProperties } } } = instance
console.log(globalProperties.$apiBase)
}
useGlobalProperties(),复用逻辑。适合挂载简单、稳定、无状态的工具函数或常量;不适合挂复杂状态或响应式对象。
$formatDate、$http(封装好的请求函数)、$message(UI 提示方法)$user(用户信息建议用 Pinia 管理)、$router(已通过 useRouter 提供)、响应式数据(会丢失响应性)$ 前缀(如 $utils),和 Vue 内置属性($emit、$refs)保持风格一致,也便于区分。