我正在使用 Typescript 和 Vuejs 来构建应用程序。我有几个独立组件 (.vue) 文件,我正在将它们导入到 Typescript (.ts) 文件中。在 Typescript 文件中,我从 npm Vue 库导入 Vue,然后创建一个新的 Vue 来显示我的组件。我看到的错误是:
“Vue”类型上不存在属性 x
我的构建系统是带有 tsc 的 Webpack。为什么我会收到此错误以及如何解决它?
import Vue from 'vue';
import Competency from '../components/competency.vue';
new Vue({
el: "#app",
components: {
'competency': Competency
},
data:{
count: 0
},
methods:{
initialize: function(){
this.count = count + 1; // Errors here with Property count does not exist on type vue
}
}
})
{
"compilerOptions": {
// "allowJs": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"lib": [
"es2015",
"dom",
"es2015.promise"
],
"module": "es2015",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitAny": false,
//"outDir": "./build/",
"removeComments": false,
"sourceMap": true,
"target": "es5"
},
"exclude": [
"./node_modules",
"wwwroot",
"./Model"
],
"include": [
"./CCSEQ",
"./WebResources"
]
}
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
Evaluations: './WebResources/js/main.ts'
},
devServer: {
contentBase: './dist'
},
module: {
rules: [{
test: /\.ts$/,
exclude: /node_modules|vue\/src/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/]
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
esModule: true
}
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
]
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
filename: 'Evaluations.html',
template: './WebResources/html/Evaluations.html'
}), new HtmlWebpackPlugin({
filename: 'ExpenseUpload.html',
template: './WebResources/html/ExpenseUpload.html'
}), new webpack.optimize.CommonsChunkPlugin({
name: 'WebAPI'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
我遇到了同样的问题,但是导出组件。 一些 VS 代码片段创建的模板没有必要的类型,如下所示
export default {
data() {
return {
x: "something",
};
},
methods: {
rename(name: string) {
this.x = name;
},
},
};
defineComponent()
来导出默认值。应该是这样
import { defineComponent } from "vue";
export default defineComponent({
data() {
return {
x: "something",
};
},
methods: {
rename(name: string) {
this.x = name;
},
},
});
确保您使用
defineComponent()
函数导出组件。
添加另一个答案以汇集您可能需要解决的几个问题。
同时
import Competency from '../components/competency';
和
import Competency from '../components/competency.vue';
可能会编译成功,第二个将有助于避免在某些IDE(例如VS Code)中出现错误。
正如 @May 上面指出的,您需要一个导入和重新导出“Vue”类型的文件。在@May的回答中,它被命名为
vue-file-import.d.ts
,但在互联网上的其他地方,它通常被称为vue-shim.d.ts
。无论名称如何,所需的内容都是相同的:
// vue-file-import.d.ts
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
本来我把它放在
/src
。我发现这有一个奇怪的效果。有时它会起作用,即 VS Code 错误消息消失了;有时却没有出现,它们又出现了。当我在项目中移动编辑不同的文件时,这种情况会动态发生。
我后来找到了内容相同的填充文件的建议,但放置在
/typings
中。我尝试过这个并且它一直有效。其他人似乎对/src
的位置很满意。
vue-文件导入.d.ts
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
有同样的问题。 解决方案是为每个计算变量添加返回类型。
从此代码发出,没有返回类型。
computed: {
containerClass() {
return this.isLastChild
}
添加返回类型String。
computed: {
containerClass(): String {
return this.isLastChild
}
@sherwin water 的回答对我帮助很大。我意识到,一旦添加
computed
字段,就会出现错误。解决方案很简单:为计算字段添加返回类型。
// wrong
computed: {
someThing() {
const { a, b } = this;
return a + b;
}
}
// correct
computed: {
someThing(): number {
const { a, b } = this;
return a + b;
}
}
我试图关注此页面https://v2.vuejs.org/v2/guide/routing.html并且遇到相同的TypeScript错误,我通过将Vue实例强制转换为类似这样的类型来修复它
new Vue({
el: '#app',
data: {
currentRoute: window.location.pathname
},
computed: {
ViewComponent() {
return routes[(this as any).currentRoute] || routes['/']
}
},
render (h) { return h((this as any).ViewComponent) }
})
我建议在使用 TypeScript 时使用基于类的组件(查看“使用 Vue.js 和 TypeScript 编写基于类的组件”)。这是获得类型安全代码并使用 IDE 的自动完成功能的唯一方法
这是基于类的组件的示例:
import { Component, Vue, Watch } from 'vue-property-decorator'
@Component({
props: {
prop1: { type: Number }
}
})
export default class MyComponent extends Vue {
// This is how you define computed
get myComputedRoute() {
return this.$route.params;
}
@Watch('myComputedRoute')
onPropertyChanged(value: string, oldValue: string) {
// Do stuff with the watcher here.
}
}
如果您使用的是 typescript 和 vue2,您应该使用
Vue.component
或 Vue.extend
来定义组件。
import Vue from 'vue'
const Component = Vue.extend({
...
})
我遇到了类似的问题(尤其是在 .vue 文件中)。不过,我确实发现这似乎解决了问题。无论您在何处导入 .vue 文件,请将 ES6 样式“import”更改为“require”。
因此,在您的示例中,更改:
import Competency from '../components/competency.vue';
到...
declare var require: any;
var Competency = require("../components/competency.vue").default;
我在 vue 2.8.2 和 Typescript 2.5.3 中遇到了同样的错误。我通过将 Vue 实例保存在变量中然后给它一个类型来修复它。这确保当您使用选项对象实例化 TS 时,TS 将了解所有 Vue 属性。
var VueApp: any = Vue;
var App = new VueApp({
el: "#app",
data() {
return {
count: 0
}
},
methods:{
initialize() {
this.count = count + 1; // Should work now
}
}
})
请勿使用任何
使用
Object.assign(vm, source);
代替
喜欢
const source= {count: this.count }
Object.assign(this, source);
在 VSCode 中,我通过完全退出 VSCode 并再次打开它来解决这个问题。
尝试使用 Typescript 的泛型。请参阅https://www.typescriptlang.org/docs/handbook/generics.html
new Vue<{ count: number }, { initialize: () => void }, {}, {}>({
//...
data:{
count: 0
},
methods:{
initialize: function() {
this.count = count + 1;
},
}
});