系列目錄: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
的基礎示例。