尝试使用Vue
和TypeScript
构建单个文件组件。我经常遇到错误。
[Vue warn]: Property or method "foo" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property
FooBar.vue
<template lang="pug">
section.section
span {{ foo }}
</template>
<script lang="ts">
import Vue from 'vue'
interface State {
foo: string
}
export default Vue.extend({
data(): State {
return {
foo: '',
}
},
mounted() {
this.foo = "Bar";
}
})
</script>
现在,如果删除lang="ts"
属性和State接口,则可以正常工作。在这里茫然。这是应用程序的其余部分。忽略我刚刚尝试过的混乱工作。
tsconfig.json
{
"compileOnSave": true,
"compilerOptions": {
"strict": true,
"moduleResolution": "node",
"target": "es6",
"noImplicitAny": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"sourceMap": true,
"baseUrl": ".",
"paths": {
"~/*": [
"./*"
],
"@/*": [
"./*"
]
}
},
"include": [
"./components/*.ts",
"./components/*.vue",
"./components/**/*.ts",
"./components/**/*.vue"
],
"files": [
"./src/vue-shims.d.ts"
],
"exclude": [
"node_modules"
]
}
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const AssetsPlugin = require('assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = function (env = {}) {
if (env.production) {
process.env.NODE_ENV = 'production';
}
function makeStyleLoader(type) {
const cssLoader = {
loader: 'css-loader',
options: {
minimize: env.production
}
};
const loaders = [cssLoader];
if (type) {
loaders.push(type + '-loader');
}
if (env.production) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
});
} else {
return ['vue-style-loader'].concat(loaders);
}
}
// Determine plugins per environment
let plugins;
if (env.production) {
plugins = [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new ExtractTextPlugin({
filename: 'css/style.min.css?[contenthash]'
}),
new AssetsPlugin({
filename: 'assets.json',
path: path.resolve(__dirname, '../public/assets'),
fullPath: false
})
];
} else if (env.standalone) {
plugins = [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
hash: true,
template: './src/index.html',
filename: './index.html' //relative to root of the application
})
];
} else {
plugins = [
new webpack.HotModuleReplacementPlugin()
];
}
return {
entry: './main.js',
output: {
path: path.resolve(__dirname, '../vue/public'),
publicPath: env.production ? '/public/' : 'http://localhost:8080/',
filename: env.production ? 'js/main.min.js?[chunkhash]' : 'js/main.js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
pub: 'pug-loader',
css: makeStyleLoader(),
less: makeStyleLoader('less'),
ts: 'ts-loader'
}
}
},
{
test: /\.pug$/,
exclude: /node_modules/,
loader: 'pug-loader',
},
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/],
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: makeStyleLoader()
},
{
test: /\.less$/,
use: makeStyleLoader('less')
},
{
test: /\.(png|jpg|svg)$/,
loader: 'url-loader'
}
]
},
plugins: plugins,
resolve: {
extensions: ['.ts', '.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
Components: path.resolve(__dirname, 'components/'),
Store: path.resolve(__dirname, 'store/'),
Src: path.resolve(__dirname, 'src/'),
Assets: path.resolve(__dirname, 'assets/')
}
},
performance: {
hints: false
},
devServer: {
historyApiFallback: true,
disableHostCheck: true,
noInfo: true,
quiet: true,
clientLogLevel: 'silent',
contentBase: false,
hot: true,
headers: {
'Access-Control-Allow-Origin': '*'
}
},
devtool: env.production ? false : '#cheap-module-eval-source-map'
};
};
main.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Vuex from "vuex";
import App from './components/App';
import FooBar from './components/FooBar';
Vue.use(VueRouter);
const router = new VueRouter({
routes: [
{ path: '/', component: FooBar }
],
mode: 'history'
});
Vue.use(Vuex);
import application from './store/Application';
const store = new Vuex.Store({
modules: {
application
}
});
const app = new Vue({
router,
store,
render: h => h(App)
}).$mount('#app');
package.json
{
"name": "foo-bar-demo",
"description": "Demo",
"version": "0.1.0",
"author": "John Doe",
"scripts": {
"dev": "node clean.js && webpack-dev-server",
"standalone": "node clean.js && webpack-dev-server --env.standalone",
"build": "webpack --env.production"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"dependencies": {
"axios": "^0.19.0",
"bulma": "^0.7.5",
"vue": "^2.5.13",
"vue-resource": "^1.3.5",
"vue-router": "^3.1.3",
"vuex": "^3.1.1"
},
"devDependencies": {
"assets-webpack-plugin": "^3.5.1",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"eslint-config-prettier": "^4.1.0",
"eslint-plugin-prettier": "^3.0.1",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.4",
"html-webpack-plugin": "^3.2.0",
"jest": "^24.1.0",
"less": "^2.7.3",
"less-loader": "^4.0.5",
"prettier": "^1.16.4",
"pug": "^2.0.4",
"pug-loader": "^2.4.0",
"ts-loader": "^6.2.0",
"typescript": "^3.6.3",
"vue-class-component": "^7.1.0",
"vue-jest": "^4.0.0-0",
"vue-loader": "^14.2.2",
"vue-property-decorator": "^8.2.2",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.2"
}
}
答案 0 :(得分:1)
如果要使用打字稿,则必须使用npm或yarn安装它,因为默认情况下vue使用javascript。
通过此链接输入打字稿: https://www.npmjs.com/package/typescript
因此,当您删除lang=ts
时,它会将脚本读取为javascript。
答案 1 :(得分:0)
三天后解决。我必须将ts-loader包含在webpack.config.js中的vue规则中
ts: [
{
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/]
}
}
]