Добавить глобальные свойства в Vue 3 с помощью TypeScript

Я хочу добавить глобальное свойство в приложение Vue 3, например, предложенное здесь

Подход прототипа не работает с 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
  }
}

Я хочу загрузить некоторые локальные файлы конфигурации с помощью области разработки или прод. Файлы с заданной областью не будут зарегистрированы в репозитории 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.

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 alt="Vue logo" src="./assets/logo.png" />
  <p>{{ $config.prop1 }}</p>
</template>

IntelliJ жалуется на неизвестную переменную prop1, но это работает.

Я много искал, но не нашел способа вставить мою $ config в метод настройки, который используется с api композиции.


person Nabor    schedule 01.10.2020    source источник
comment
Я много искал, но не нашел способа вставить мою $ config в метод настройки, который используется с api композиции. - Я пропустил эту часть разговора, это в конечном итоге немного нарушает условия сделки, поскольку теперь у меня есть глобальная переменная, которую я могу использовать везде, кроме логики настройки, по этой причине подход с предоставлением-инъекцией потенциально лучше   -  person Sam    schedule 09.11.2020


Ответы (2)


Вы можете дополнить модуль @vue/runtime-core TypeScript в своем приложении:

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

аналогично тому, как этот работал в Vue 2.

Кажется, это еще не вошло в документацию Vue 3, но было введено в vuejs / vue-next # 982. Оформить заказ на

person namoscato    schedule 03.10.2020
comment
Не забудьте добавить import Vue from 'vue' перед расширением модуля, как определено в связанной документации. - person Julien Leicher; 13.01.2021
comment
Таааааааааааааааааааааааалов)) у меня это никогда не работало, Vue 2 или 3. По крайней мере, Vetur это не нравится. Я разрабатываю локальную зависимость. Кто-нибудь заставил это работать в том же контексте, что и я? - person Luke Pring; 23.02.2021
comment
компилятору это немного не нравится `Module '../../../node_modules/vue/dist/vue' не имеет экспортированного члена 'defineComponent'.` ?? - person Exlord; 04.04.2021
comment
чтобы увеличить globalProperties, который вам нужен при импорте, сначала import { ComponentCustomProperties } from 'vue';, иначе компилятор будет жаловаться на это - person Exlord; 04.04.2021

В Vue 3 вы вызываете метод use в экземпляре вашего приложения, а не в методе Vue var.

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

Кроме того, вам необходимо написать свой плагин в соответствии с ожиданиями Vue 3 (объект с методом install).

Ознакомьтесь с руководством по Vue 3 по написанию и использованию плагинов, в нем описан очень похожий вариант использования. к твоему.

Кстати, *.d.ts файлы предназначены для использования в качестве файлов деклараций для объявления типов, обычно в качестве дополнения к нетипизированным модулям (например, для ввода существующего кода js). Обычно вам не нужно самостоятельно писать *.d.ts файлы при написании кода Typescript (объявления могут быть автоматически сгенерированы компилятором tsc).

person danielv    schedule 01.10.2020
comment
Спасибо за подсказку. Не могли бы вы поподробнее? Обновил вопрос. - person Nabor; 01.10.2020