Vue JS typescript 组件找不到注入实例属性

Dan*_*tos 7 javascript typescript vue.js vuejs2

我正在使用 typescript 和 vue。

在我的应用程序中service,每个子组件都有一个全局变量。

我在 vue JS 上找到了这个原生 vue 解决方案,将这个属性注入到子组件上。

在 main.ts 上

const service = new MyService(...);

new Vue({
  router,
  provide() { return { service }; } // provide the service to be injected
  render: h => h(App),
}).$mount("#app");
Run Code Online (Sandbox Code Playgroud)

在任何 typescript vue 组件上

import Vue from "vue";

export default Vue.extend({
  inject: ["service"], // inject the service
  mounted() {
    console.log(this.service); // this.service does exists 
  },
});
Run Code Online (Sandbox Code Playgroud)

这样我就可以service在我的 Child 组件上注入。

但是我收到了休闲错误

“CombinedVueInstance < Vue, {}, {}, {}, Readonly < Record < never, any > >”类型上不存在属性“service”。

我该如何解决这个打字稿编译错误?

Ale*_*lex 5

使用插件

如果您想在所有 Vue 组件中使用某些服务,您可以尝试使用插件。
在 main.ts 中,您只需导入它:

import Vue from "vue";
import "@/plugins/myService";
Run Code Online (Sandbox Code Playgroud)

在plugins/myService.ts你必须写这样的东西:

import _Vue from "vue";
import MyService from "@/services/MyService";

export default function MyServicePlugin(Vue: typeof _Vue, options?: any): void {
    Vue.prototype.$myService = new MyService(...); // you can import 'service' from other place
}

_Vue.use(MyServicePlugin);
Run Code Online (Sandbox Code Playgroud)

在任何 vue 组件中你都可以使用这个:

<template>
  <div> {{ $myService.name }}</div>
</template>
<script lang="ts">
  import { Component, Vue } from "vue-property-decorator";

  @Component
  export default class MyComponent extends Vue {
    private created() {
      const some = this.$myService.getStuff();
    }
  }
</script>
Run Code Online (Sandbox Code Playgroud)

不要忘记$myService在d.ts文件中声明。在您的项目中的某处添加myService.d.ts具有以下内容的文件:

import MyService from "@/services/MyService";

declare module "vue/types/vue" {
  interface Vue {
      $myService: MyService;
  }
}
Run Code Online (Sandbox Code Playgroud)


Ser*_*eon 2

\xc2\xa0使用Vue属性装饰器

\n

Vue-property-decorator ,它在内部从vue-class-component重新导出装饰器,公开了一系列提供真正良好智能感知的打字稿装饰器。但您必须使用类 api。

\n

@Inject是@Provide这样的装饰器中的两个:

\n

在提供者中:

\n
import {Vue, Component, Provide} from \'vue-property-decorator\';\n\n@Component\nexport default class MyClass {\n  @Provide(\'service\') service: Service = new MyServiceImpl(); // or whatever this is\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在提供的组件中:

\n
import {Vue, Component, Inject} from \'vue-property-decorator\';\n\n@Component\nexport default class MyClass {\n  @inject(\'service\') service!: Service; // or whatever type this service has\n  mounted() {\n    console.log(this.service); // no typescript error here\n  },\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我认为这是最佳解决方案,从某种意义上说,它在使用 Vue 时提供了更好的智能感知。

\n

然而,现在您可能不想更改所有组件的定义,或者由于外部限制而无法更改。在这种情况下,你可以采取下一个技巧:

\n

铸造这个

\n

每当您this要使用this.service. 可能不是最好的事情,但它有效:

\n
  mounted() {\n    console.log((this as any).service);\n  },\n
Run Code Online (Sandbox Code Playgroud)\n

肯定还有其他方法,但是我已经不习惯Vue.extendsapi了。如果你有时间和机会,我强烈建议你切换到类 API 并开始使用 vue-property-decorators,它们确实提供了最好的智能感知。

\n