这篇教程适用于手动构建的 vue 项目和 vue-cli 2x 版本的脚手架自动构建的项目。
vue/cli 3x 版本以上的脚手架可以在自动构建时自选集成的 typescript 环境,这并不有利于学习。
新建 vue 项目
我这里采用 2x 的脚手架自动构建个 vue 项目。
vue init webpack platform-test
按照如下截图依次选择即可:
构建完项目之后进入,查看项目的目录结构如下:
改造项目
安装依赖项
需要新增些依赖项。
ts 和 tslint 相关,这是必须要的:
- ts-loader
- typescript
- tslint
- tslint-config-standard
- tslint-loader
以下两个是方便写 ts 的依赖项,可选
- vue-class-component 扩展 vue 支持 typescript,将原有的 vue 语法通过声明的方式来支持 ts
- vue-property-decorator 基于 vue-class-component 扩展更多装饰器
但由于存在很复杂的各依赖项的版本冲突,还有依赖项是需要升级的。
例如,目前项目中的 vue 和 webpack 版本,与如上直接安装最新的 typescript、ts-loader 版本就存在冲突,不仅文件中存在红色波浪线的提示,还有编译时的报错。
这时候就需要降低 typescript、ts-loader 的版本,但你又会发现原本 ts 的类型声明文件写法又会有问题,那还是升级 webpack 的版本比较好......
总之版本问题挺麻烦的。
我这里测试整理出一套有效的依赖项版本,直接复制到项目的 package.json 中
"dependencies": {
"vue": "^2.5.2",
"vue-class-component": "^7.2.6",
"vue-property-decorator": "^9.1.2",
"vue-router": "^3.0.1"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eslint": "^4.19.1",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^2.0.0",
"eslint-plugin-html": "^3.0.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-typescript": "^0.11.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^3.2.0",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"ts-loader": "^4.4.2",
"tslint": "^6.1.3",
"tslint-config-standard": "^9.0.0",
"tslint-loader": "^3.5.4",
"typescript": "^3.5.2",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^15.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^4.5.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^3.5.1",
"webpack-merge": "^4.1.0",
"webpack-cli": "^3.3.2"
},
删除整个 node_modules,如果有 package-lock.json 这个文件也要删掉,然后重新安装所有依赖项,
yarn
文件改造
tsconfig.json
首先执行个命令,生成个 tsconfig.json
tsc --init
文件中内容修改如下:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["*", "src/*"]
},
"jsx": "preserve",
"jsxFactory": "h",
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"allowJs": true,
"module": "esnext",
"target": "es5",
"moduleResolution": "node",
"isolatedModules": true,
"lib": ["dom", "es5", "es6", "es7", "es2015.promise"],
"sourceMap": true,
"pretty": true,
"typeRoots": ["src/types"]
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
类型声明文件
src 中新建个 types 文件夹,以后所有的类型声明文件都放这儿了。
types 中新建个文件 index.d.ts
import "./global";
types 中新建个文件 global.d.ts,这个就是让 ts 识别 vue 文件,不然 js 文件改成 ts 之后,引用的 vue 全是红色波浪线,
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
js 改 ts
如果是按照前文构建的 vue 项目,这时项目中应该只有两个 js 文件,
- main.js
- router 中 index.js
直接修改文件名尾缀,js 变 ts
main.ts 中引用 vue 那条语句仍报错,完善文件名就好了
import App from "./App.vue";
修改.eslintrc.js
修改其中的 parser
parser: "@typescript-eslint/parser";
修改 webpack 基础配置文件
项目根目录 build 文件下,webpack.base.conf.js 中,有四点需要修改。
- entry 中入口文件的 main.js 修改成 main.ts
2) resolve 中 extensions 需要识别的文件新增 ts 文件类型,
extensions: [".js", ".vue", ".json", ".ts"],
- module 的 rules 中新增 ts 的 loader,新增在 js 的 loader 之前
{
test: /\.tsx?$/,
exclude: /node_modules/,
// loader: 'ts-loader',
use: [
"babel-loader",
{
loader: "ts-loader",
options: { appendTsxSuffixTo: [/\.vue$/] }
},
{
loader: "tslint-loader"
}
]
},
- 修改原有配置中 vueLoaderConfig 的配置方式
首先在一开始需要引入 VueLoaderPlugin
const { VueLoaderPlugin } = require("vue-loader");
再新增个 plugins 项,和 resolve、module 这些是同级
plugins: [new VueLoaderPlugin()];
最后还需要修改下 module 的 rules 中 vue 的配置
{
test: /\.vue$/,
loader: "vue-loader",
// options: vueLoaderConfig
},
至此,改造已经完成了。
使用
按照工作规范,我还是习惯把一个组件或者一个页面拆分成三个文件组成一个文件夹。
例如写的这个 demo
index.vue
{{msg}}
index.ts
import Vue from "vue";
export default Vue.extend({
data() {
return {
msg: "DEMO"
};
}
});
index.css
.main {
width: 100px;
height: 100px;
border: 1px solid red;
}
引用还是在路由那写的,
import Demo from "../components/demo/index.vue";
routes: [
{
path: "/demo",
name: "Demo",
component: Demo
}
];
那在浏览器http://localhost:8080/#/demo中就可以看到 demo 页面