使用 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 组件向外部公开数据?
Vue + VueX + Typescript + Vue 路由器。组件未销毁
typescript 使用Typescript将属性添加到Vue.js中的数组