系列目录:css
写这篇文章时的我,Vue使用经验三个多月,Typescript彻底空白,
花了大概三个晚上把手头项目迁移至Typescript,所以这篇文章更像个入门指引。vue
两大原则:node
因为我我的从Javascript到Typescript的升级,更倾向于平滑顺移,所以,我对新依赖的引入总体保持克制原则,只引入了必要项,以尽可能贴近原生vue写法:webpack
typescript
ts-loader
如下依赖均未引入:git
vue-class-component
:官方维护,学习成本小,但与vuex
融合性较差,计划等官方完善对vuex
支持后再考虑引入vue-property-decorator
:非官方维护,必定学习成本vuex-class
:非官方维护,在 vue-class-component 基础上补充必定vuex
支持(支持有限)vuex-ts-decorators
/vuex-typescript
等:非官方维护,学习成本极高PS: 后总结,vue官方维护的 vue-class-component 仍是颇有必要引入的,文末有详细说明。PS:
tslint-loader
因为对vue
的支持尚不完美,做为可选项文末有详细说明。github
any
任意类型的存在,在我看来就是个潘多拉魔盒,一旦开启,很容易养成偷懒的习惯,碰到难题就上 any
。所以,个人建议是,尽可能不要去碰它,除非你无路可走。web
注:这里只介绍Webpack模板下使用。
vue init webpack <项目名称>
生成的项目需作以下改动以兼容 Typescript:vuex
npm i --save-dev typescript ts-loader
安装必要依赖。推荐使用 npm 8及以上版本。typescript
./build/webpack.base.conf.js
,做以下改动:npm
main.js
改成main.ts
:entry: { app: './src/main.ts' }
resolve.extensions
添加.ts
:resolve: { extensions: ['.js', '.ts', '.vue', '.json'] }
module.rules
添加.ts
解析规则:module: { rules: [ { test: /\.tsx?$/, loader: 'ts-loader', exclude: /node_modules/, options: { appendTsSuffixTo: [/\.vue$/] } } ] }
项目根路径下添加文件tsconfig.json
,官方推荐配置以下:
// tsconfig.json { "compilerOptions": { // 与 Vue 的浏览器支持保持一致 "target": "es5", // 这能够对 `this` 上的数据属性进行更严格的推断 "strict": true, // 若是使用 webpack 2+ 或 rollup,能够利用 tree-shake: "module": "es2015", "moduleResolution": "node" } }
src
目录下添加文件vue-shim.d.ts
:
declare module "*.vue" { import Vue from "vue"; export default Vue; }
意思是告诉TypeScript *.vue
后缀的文件能够交给vue
模块来处理。
从src/main.js
开始,包括src/router/index.js
等逐一从.js
重命名为.ts
注意:重命名后对vue
文件的import
,需添加.vue
后缀
由于Typescript默认只识别*.ts
文件,不识别*.vue
文件
以前:
import App from './App' import HelloWorld from '@/components/HelloWorld'
需改成:
import App from './App.vue' import HelloWorld from '@/components/HelloWorld.vue'
要点:
<script>
标签添加lang="ts"
声明Vue.extend
定义组件示例:
// src/components/HelloWorld.vue <script lang="ts"> import Vue from 'vue' export default Vue.extend({ name: 'HelloWorld', data () { return { msg: 'Welcome to Your Vue.js App' } } }) </script>
至此运行项目,便可正常运行,vue对typescript的初步引入,基本完成。
2017-12-6更新:
当前(2017年12月),对.vue
文件,VSCode编辑器的编辑时提示,有了一个非官方方案(官方进度见如下issue,仍均未解决),TSLint Vue。
简单讲,一给力小哥 Fork 了 VSCode 官方的 TSLint插件,添加了对 Vue 文件的支持。小哥更新蛮频繁的,基本上第一时间跟随官方插件的最新版,亲测可用。
使用方式:VSCode Plugin,关闭 TSLint,下载并启用 TSLint Vue便可:
当前(2017年11月),对.vue
文件,能够在关闭no-consecutive-blank-lines
检查前提下,开启构建时TSLint
支持;至于VSCode编辑器的编辑时提示,彻底没有。
不幸的是,也不能拿ESLint
将就用,否则一堆以下的Error等着你:
因此,只剩俩选择,要么关了,要么按照下面的配置将就着用:
npm i --save-dev tslint tslint-loader tslint-config-standard
module.rules
移除eslint-loader
,添加tslint-loader
预处理// ./build/webpack.base.conf.js module: { rules: [ // { // test: /\.(js|vue)$/, // enforce: 'pre', // exclude: /node_modules/, // use: { // loader: 'eslint-loader', // options: { // formatter: require('eslint-friendly-formatter') // } // } // }, { test: /\.ts$/, exclude: /node_modules/, enforce: 'pre', loader: 'tslint-loader' }, { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, ] }
vue-loader
中开启tslint-loader
选项:// ./build/vue-loader.conf.js const merge = require('webpack-merge') module.exports = { loaders: merge(utils.cssLoaders({ sourceMap: isProduction ? config.build.productionSourceMap : config.dev.cssSourceMap, extract: isProduction }), { ts: ['ts-loader', 'tslint-loader'] } ), ... // 其余内容 }
tslint.json
:// tslint.json { "extends": "tslint-config-standard", "globals": { "require": true }, "rules": { "no-consecutive-blank-lines": false } }
no-consecutive-blank-lines
关闭的解释 见这里
简单翻译,vue-loader
与tslint-loader
结合使用,就像是把.vue文件里的<template>
与<style>
等非js内容所有置为了空行同样,为此,只能关闭此检查。
从新运行npm run dev
,便可看到构建时可能输出的tslint
警告(tslint默认级别warning,不阻断构建,如需error级别,可自行修改)
原生vue组件写法会致使一很烦的问题:
data()
若是以下形式定义数组,将会被推导为[]never
类型:
export default Vue.extend({ data () { return { list: [] // type: []never } } })
这样一来,此array
直接废掉,由于不能往上附加值,只能如此提早声明:
export default Vue.extend({ data () { const list: string[] = [] return { list: list } } })
而引入vue-class-component
后的class
写法,则能够一行搞定:
<script lang="ts"> import Vue from 'vue' import Component from 'vue-class-component' @Component export default class HelloWorld extends Vue { list: string[] = [] hello () { list.push('Hello world') } } </script>
我我的是考虑到 vue-class-component
对 vuex
的 mapState
, mapGetters
等函数支持较差,(能够借助vuex-class
引用),再加Decorators
并非我对typescript的核心需求(Interface
才是!),决定的暂缓引入,先不增长复杂度。
见文章 Vue2.5+ Typescript 引入全面指南 - Vuex篇
见 Github 库:vue-vuex-typescript-demo,master
分支为整合 vuex
示例,basic
分支为不含 vuex
的基础示例。