使用 TypeScript 向 Vue 3 添加全局属性

Posted

技术标签:

【中文标题】使用 TypeScript 向 Vue 3 添加全局属性【英文标题】:Add global properties to Vue 3 using TypeScript 【发布时间】:2021-01-17 04:01:16 【问题描述】:

我想向 Vue 3 应用程序添加一个全局属性,如建议的 here

原型方法不适用于 TypeScript。

我找到了一个示例,我将其转换为 config.d.ts 代码

import Vue from 'vue'

import base from '@/config/config.json'
import dev from '@/config/config.dev.json'
import prod from '@/config/config.prod.json'

let config
if (process.env.NODE_ENV === 'production') 
  config = Object.freeze(Object.assign(base, prod))
 else 
  config = Object.freeze(Object.assign(base, dev))


declare module 'vue/types/vue' 
  interface Vue 
    $config: config
  

我想加载一些具有 dev 或 prod 范围的本地配置文件。范围内的文件不会被检入 GIT 存储库。

main.ts 现在看起来像这样...

import Vue from 'vue'
import createApp from 'vue'
import App from './App.vue'
import Config from '@/plugins/config.d.ts'

Vue.use(Config)
createApp(App).mount('#app')

问题:

ERROR in src/main.ts:6:5
TS2339: Property 'use' does not exist on type 'typeof import("d:/Martin/Entwicklung/2020/STA-Electron/node_modules/vue/dist/vue")'.
    4 | import Config from '@/plugins/config.d.ts'
    5 |
  > 6 | Vue.use(Config)
      |     ^^^
    7 | createApp(App).mount('#app')
    8 |

我理想中想要实现的是一个全局的config$config属性,可以在Vue 3的setup方法中使用

export default defineComponent(
  name: 'App',
  components: ,
  setup(props, context) 
    const elem = ref(context.$config.prop1)
    const doSth = () => 
      console.log('Config', context.$config)
    
    return doSth, elem
  ,
)

我该如何解决这个问题?

更新

在 danielv 的回答之后,新插件看起来是这样的

import App from 'vue'

export interface ConfigOptions 
  base: any
  dev: any
  prod: any


export default 
  install: (app: App, options: ConfigOptions) => 
    app.config.globalProperties.$config =
      process.env.NODE_ENV === 'production'
        ? Object.freeze(Object.assign(, options.base, options.prod))
        : Object.freeze(Object.assign(, options.base, options.dev))
  ,

main.ts 也改成了这个

import createApp from 'vue'
import App from '@/App.vue'
import ConfigPlugin from '@/plugins/config'
import base from '@/config/config.json'
import dev from '@/config/config.dev.json'
import prod from '@/config/config.prod.json'

createApp(App).use(ConfigPlugin, base, dev, prod).mount('#app')

这个简单的插件可以在模板中使用

<template>
  <img  src="./assets/logo.png" />
  <p> $config.prop1 </p>
</template>

IntelliJ 抱怨未知变量 prop1,但它可以工作。

我搜索了很多,但没有办法将我的 $config 插入与组合 API 一起使用的设置方法中。

【问题讨论】:

“我搜索了很多,但没有办法将我的 $config 插入到与组合 API 一起使用的设置方法中。” - 我错过了对话的这一部分,这最终有点破坏交易,因为我现在有一个全局变量,除了设置逻辑之外,我可以在任何地方使用它,因此,提供注入方法可能更好 【参考方案1】:

您可以在应用程序中扩充@vue/runtime-core TypeScript 模块:

declare module '@vue/runtime-core' 
  interface ComponentCustomProperties 
    $config: Record<string, unknown>;
  

类似于 Vue 2 中的 used to work。

似乎这还没有进入 Vue 3 文档,但在 vuejs/vue-next#982 中引入。查看ComponentCustomProperties interface source code 了解更多信息。

【讨论】:

不要忘记在按照链接文档中的定义扩充模块之前添加import Vue from 'vue' Soooo... 这对我来说从来没有用过,Vue 2 或 3。至少 Vetur 不喜欢它。我正在开发本地依赖项。任何人都可以在与我相同的环境中使用它吗? 编译器有点不喜欢 `Module '"../../../node_modules/vue/dist/vue"' has no export member 'defineComponent'.` ?? 增加 globalProperties 你需要先导入 import ComponentCustomProperties from 'vue'; 否则编译器会抱怨它 我和@Exlord 有同样的问题。一旦我在基于 Vite 的 Vue 项目(使用 ts)中将我的输入保存在 src/typings/index.d.ts 中,似乎这会覆盖 @vue/runtime-core 输入而不是增加它们。每次我使用 defineComponent 定义一个组件时,我都会收到这个 TS 错误说Module '"../../../node_modules/vue/dist/vue"' has no exported member 'defineComponent'.。知道如何解决这个问题吗?【参考方案2】:

在 Vue 3 中,您在应用实例上调用 use 方法,它不是 Vue var 上的方法。

const app = createApp(App)
app.mount('#app')
app.use(config)

此外,您需要编写您的插件以符合 Vue 3 的预期(具有install 方法的对象)。

查看Vue 3 guide 关于编写和使用插件的内容,它描述了一个与您非常相似的用例。

顺便说一句,*.d.ts 文件旨在用作纯声明文件来声明类型,通常作为对其他无类型模块的补充(例如,键入现有的 js 代码)。编写Typescript代码时一般不需要自己编写*.d.ts文件(声明可以由tsc编译器自动生成)。

【讨论】:

感谢您的提示。你能再详细一点吗?我更新了问题。 来自纯 TS 项目:我想知道您的说法“您通常不需要编写 *.d.ts 文件”。你如何声明一个在你的项目中使用了一百次的类型?我们有一个 global.d.ts 文件并将其放在那里。 Afaik 这是一个常见的用例。 是的,这是一种常见的做法,当然也是有效的做法,但一般来说,typescript 不鼓励全局类型,而是支持范围和命名空间类型。您可以使用 d.ts 文件,但这些文件的主要目的是在它们不可用时提供输入(例如,使用无类型的 javascript 时),如果必须,您还可以在 *.ts 文件中声明全局类型。这没有错,只是通常您不一定需要或想要它们。

以上是关于使用 TypeScript 向 Vue 3 添加全局属性的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Typescript Vue 组件向外部公开数据?

vite + vue3 添加 typescript

Vue + VueX + Typescript + Vue 路由器。组件未销毁

typescript 使用Typescript将属性添加到Vue.js中的数组

更改(映射)JSON列表形状 - 在TypeScript中向对象添加标记

Vue中使用TypeScript