和Vue3全局属性说再见?

先看这段强迫症爆炸的代码😤:

js 复制代码
<script lang="ts" setup>
import { getCurrentInstance } from 'vue';

const { $loading } = getCurrentInstance()?.appContext.config.globalProperties ?? {}; // 繁琐,且还需要去额外地定义$loading的类型,不然ts会报类型错误
</script>

setup 中无法直接通过 this 访问全局属性(如 app.config.globalProperties 定义的属性),需借助 getCurrentInstance(),导致代码出现了冗长的链式调用,而且每个组件里都要重新写这段导入和获取实例的代码。

缺点:

  • 不支持tree-shaking
  • 代码冗余
  • 类型需要额外定义,否则报错
  • 可读性差

改造第一步:Hook封装 🪝

js 复制代码
// symbols.ts
export const GLOBAL_API = Symbol('unique_api_key')

// hooks/useGlobal.ts
import { ComponentInternalInstance, getCurrentInstance } from 'vue';

export default function useGlobal() {
  const instance = getCurrentInstance() as ComponentInternalInstance;
  return instance.appContext.config.globalProperties;
}

// 使用端:直接解放双手?
import useGlobal from "@/hooks/useGlobal";
const { $loading } = useGlobal(); // 还是需要去额外配置$loading的类型,否则会默认是any类型

在使用端还是会需要先import才能获取到所需的全局属性。 不过用了自动引入插件配置后也就没有import 问题了。

优点:

  • 代码量减少70%
  • 统一访问入口
  • 没有类型报错,但会默认为any类型

缺点:

  • vue全局属性不支持tree-shaking

改造第二步:改用Provide/Inject 🥀

js 复制代码
// main.ts
import { $loading } from "@/utils";
app.provide('$loading', $loading); // 减少了冗长的前置代码

// 使用端:更简单了吗?
const $loading = inject('$loading')!

作为一个比全局属性/Hooks开销更大的功能,在使用端与Hook封装的使用感基本无差别,仅仅是减少了入口代码量。而且经过测试,还是无法支持tree-shaking。

改造第三步:化繁为简 🍵

既然都已经弃用全局属性了,何不直接连全局概念也弃用?

js 复制代码
// 使用端
// import { $loading } from "@/utils"; // 使用unplugin-auto-import配置后,省去import语句
$loading.start();

这种最简单引入的方式本身就能正常支持tree-shaking。

总结

  • 变量/函数只在<template></template>中使用:可用全局属性(无需使用getCurrentInstance)
  • 变量需要响应式:用Hooks或者Provide/Inject
  • 不需要响应式的变量/函数:直接import

进阶

对于静态数据,直接用Vite配置

js 复制代码
// vite.config.ts
export default defineConfig({
  define: {
    __APP_INFO__: JSON.stringify({
      version: '1.2.0',
      buildTime: new Date().toLocaleString()
    })
  }
})

// 使用端:零成本调用
console.log(__APP_INFO__.version) // 但需要单独类型定义
// global.d.ts
declare const __APP_INFO__: {
  version: string;
  buildTime: string;
};

优点:

  • 零运行时开销:因为是构建时静态替换
  • 自动tree-shaking
  • 与业务代码解耦
相关推荐
2301_32241428047 小时前
活力孕康复APP 47737- 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·mysql·微信小程序·idea·微信开发者工具
专业程序开发源8 小时前
springbootLivehouse票务系统-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·课程设计·pygame
leoZ2318 小时前
2026-09-10-静态扫描连错三次-用运行环境当裁判
前端·javascript·vue.js·人工智能·opencv·机器学习·数据挖掘
卓怡学长9 小时前
w233基于vue和springboot的宠物管理系统的设计与实现
java·vue.js·spring boot·spring·intellij-idea
梨涡泥窝11 小时前
JavaWeb——基于 Spring Boot + Vue 的图书管理系统的设计与实现
vue.js·spring boot·后端
huali13 小时前
vue-split-screen:让 Vue Router 的导航轨迹变成两个页面
前端·javascript·vue.js
雪芽蓝域zzs14 小时前
第三十六节:keep-alive 页面缓存(Vue3 + 后台管理系统)
前端·vue.js·缓存
边境悍匪15 小时前
蜗牛学苑 Java 智能体学习 Day41|ElementPlus 布局、Vue‑Router 登录、Axios 思维导图复盘
java·vue.js·学习
志尊宝15 小时前
Vue3 零基础每日笔记(017):事件处理进阶——$event、多事件与事件修饰符全家桶
javascript·vue.js·笔记
Bs_MoneyMagnet1 天前
基于springboot+vue的医疗健康便民服务平台的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring