我正在使用打字稿和vue。
在我的应用中,有一个service
,它是每个子组件的全局变量。
我在vue JS上发现了this native vue solution,将该属性注入了子组件。
在main.ts上
const service = new MyService(...);
new Vue({
router,
provide() { return { service }; } // provide the service to be injected
render: h => h(App),
}).$mount("#app");
在任何打字稿vue组件上
import Vue from "vue";
export default Vue.extend({
inject: ["service"], // inject the service
mounted() {
console.log(this.service); // this.service does exists
},
});
这样,我就可以在自己的Child组件上获得注入的service
。
但是我遇到了休闲错误
类型'CombinedVueInstance
>>'上不存在属性'service'。
如何解决此打字稿编译错误?
答案 0 :(得分:2)
您无需使用类组件即可获取此信息。对于对象组件声明,您有两种方法可以做到:
export default {
inject: ['myInjection'],
data(): { myInjection?: MyInjection } {
return {}
},
}
缺点是您必须将其标记为可选,才能添加它以进行数据返回。
declare module 'vue/types/vue' {
interface Vue {
myInjection: MyInjection
}
}
export default {
inject: ['myInjection'],
}
答案 1 :(得分:1)
Vue-property-decorator从vue-class-component内部重新导出修饰符,它暴露了一系列打字稿修饰符,这些修饰符确实具有很好的智能感。不过,您必须使用类api。
@Inject
和@Provide
是两个这样的修饰符:
在提供者中:
import {Vue, Component, Provide} from 'vue-property-decorator';
@Component
export default class MyClass {
@Provide('service') service: Service = new MyServiceImpl(); // or whatever this is
}
在提供的组件中:
import {Vue, Component, Inject} from 'vue-property-decorator';
@Component
export default class MyClass {
@inject('service') service!: Service; // or whatever type this service has
mounted() {
console.log(this.service); // no typescript error here
},
}
我认为这是最佳的解决方案,从某种意义上说,它提供了使用Vue时更好的智能感知。
但是,现在,您可能不想更改所有组件的定义,或者只是由于外部限制而不能更改。在这种情况下,您可以执行下一个技巧:
只要您要使用this
,就可以将this.service
强制转换为任意值。可能不是最好的东西,但是它可以工作:
mounted() {
console.log((this as any).service);
},
肯定还有其他方法,但是我已经不习惯使用Vue.extends
api了。如果有时间和机会,我强烈建议您切换到类API并开始使用vue-property-decorator,它们确实可以提供最佳的智能感知。
答案 2 :(得分:1)
如果您想在所有Vue组件中使用某些服务,则可以尝试使用plugins。
在main.ts中,您只需导入它即可:
import Vue from "vue";
import "@/plugins/myService";
在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);
在任何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>
请不要忘记在$myService
文件中声明d.ts
。在项目中的某处添加文件myService.d.ts
,其内容如下:
import MyService from "@/services/MyService";
declare module "vue/types/vue" {
interface Vue {
$myService: MyService;
}
}
答案 3 :(得分:1)
为注入创建一个接口并在需要的地方为特定组件扩展Vue:
main.ts:
const service = new MyService(...);
export interface ServiceInjection {
service: MyService;
}
new Vue({
router,
provide(): ServiceInjection { return { service }; } // provide the service to be injected
render: h => h(App),
}).$mount("#app");
使用你的界面的组件
import Vue from "vue";
import { ServiceInjection } from 'main.ts';
export default ( Vue as VueConstructor<Vue & ServiceInjection> ).extend({
inject: ["service"], // inject the service
mounted() {
console.log(this.service); // this.service does exists
},
});