0Pricing
Vue Academy · 课时

插件中的全局属性与 provide/inject

app.config.globalProperties.$myPlugin、使用 app.provide() 进行注入,以及 TypeScript 扩展

插件中的全局属性与 provide/inject 是 CoddyKit 上的免费 Vue Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Vue Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Vue Academy 课程共包含 4 节课。

公开服务的两种方式

插件可以通过两种方式共享功能:全局属性(经典的选项式 API 风格,通过 this.$x 访问)以及provide/注入(组合式 API 风格)。现代代码更倾向于使用 provide/注入;对于选项式 API 代码库,全局属性仍然很有用。

app.config.globalProperties

app.config.globalProperties.$http = client 会让每个选项式 API 组件都能使用 this.$http。按照惯例,属性应以 $ 开头,以避免与组件数据冲突。

import axios from 'axios'

export default {
  install(app, options) {
    const http = axios.create({ baseURL: options.baseURL })
    app.config.globalProperties.$http = http
  }
}

在选项式 API 中使用 $http

在选项式 API 组件内部,可以通过 this 访问全局属性。

export default {
  async created() {
    const res = await this.$http.get('/users')
    this.users = res.data
  },
  data() {
    return { users: [] }
  }
}

为什么组合式 API 无法使用 this

在 <script setup> 中,没有绑定到组件实例的 this。因此 this.$http 无法工作。组合式 API 会改为读取注入的值,这是推荐的方式。

<script setup>
// this is undefined here, so this.$http is NOT available
// use inject() instead
</script>

在插件中使用 provide

为了支持组合式 API,插件还应通过 app.provide 使用一个键提供同一个 service。两种方式都要提供:为选项式 API 提供全局属性,为组合式 API 使用 provide。

export const httpKey = Symbol('http')

export default {
  install(app, options) {
    const http = createHttp(options)
    app.config.globalProperties.$http = http // Options API
    app.provide(httpKey, http)               // Composition API
  }
}

在组合式 API 中注入

组件通过 inject(httpKey) 读取 service。使用导出的 Symbol 键可以避免字符串拼写错误,并支持类型推断。

<script setup>
import { inject } from 'vue'
import { httpKey } from './plugins/http'

const http = inject(httpKey)
const res = await http.get('/profile')
</script>

使用 InjectionKey 设置类型化注入键

要实现完整的类型安全,请使用 InjectionKey<T> 为键指定类型。这样,inject 就能自动推断出正确的值类型。

import type { InjectionKey } from 'vue'
import type { AxiosInstance } from 'axios'

export const httpKey: InjectionKey<AxiosInstance> =
  Symbol('http')

// inject(httpKey) is now typed as AxiosInstance | undefined

使用模块扩展为 $http 添加类型

要让 this.$http 具备类型安全,请在 .d.ts 文件中扩展 Vue 的 ComponentCustomProperties 接口。这样,TypeScript 就能在任何地方识别 this.$http 的类型。

// shims.d.ts
import type { AxiosInstance } from 'axios'

declare module 'vue' {
  interface ComponentCustomProperties {
    $http: AxiosInstance
  }
}

export {}

扩展应放在哪里

扩展必须是一个模块(注意末尾的 export {}),并且要包含在您的 tsconfig.json 中。请将它放在插件旁边,这样发布插件时类型也会随之提供。

// tsconfig.json (excerpt)
{
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"]
}

请谨慎使用全局属性

全局属性虽然方便,却会形成隐藏的依赖,使组件更难测试和推理。请优先使用 provide/注入(依赖明确且限定在组件树范围内)。只有真正适用于整个 app 且方便选项式 API 使用的工具,才应使用全局属性。

同时支持两种模式

完善的插件应同时支持选项式 API 和组合式 API:设置全局属性 AND 提供该值,并为全局属性和类型化注入键提供类型扩展。使用者可以根据组件风格选择合适的方式。

install(app, options) {
  const service = build(options)
  app.config.globalProperties.$service = service
  app.provide(serviceKey, service)
}

快速检查

请检验您对插件中的全局属性和 provide/注入的理解。

回顾

您学会了如何公开插件服务:

  • app.config.globalProperties.$http 为选项式 API 的 this.$http 提供支持
  • 组合式 API 没有 this,而是使用 inject
  • 同时提供全局属性和所提供的值,以实现完整覆盖
  • 通过扩展 ComponentCustomProperties 为 this.$http 添加类型
  • 使用类型化的 InjectionKey 处理注入路径

常见问题解答

「插件中的全局属性与 provide/inject」课时是免费的吗?

是的 — 「插件中的全局属性与 provide/inject」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Vue Academy 课程的其余内容,请升级到 CoddyKit PRO。 Vue Academy 课程共包含 4 节课。

「插件中的全局属性与 provide/inject」这节课中我会学到什么?

app.config.globalProperties.$myPlugin、使用 app.provide() 进行注入,以及 TypeScript 扩展 你通过在浏览器中直接运行的动手代码来练习 Vue Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Vue Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Vue Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「插件中的全局属性与 provide/inject」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Vue Academy 课中编写并运行代码吗?

能。每节 Vue Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 插件架构与 app.use()
  2. 插件中的全局属性与 provide/inject
  3. 通知与 Toast 插件示例
  4. 发布 Vue 插件并添加类型
← 返回 Vue Academy