本文譯自 Integrate TypeScript in your Vue project,如有侵權(quán)請(qǐng)聯(lián)系rodrickjue@hotmail.com
你有一個(gè) Vue 項(xiàng)目并且你聽說(shuō) TypeScript 對(duì)項(xiàng)目會(huì)有很大的幫助。然后你決定開始使用Typescript。那么這將會(huì)是一個(gè)能夠簡(jiǎn)單快速完成這一點(diǎn)(在Vue項(xiàng)目中集成Typescript)的教程。
在這篇文章中我們假設(shè)你已經(jīng)在使用SFC(Single File Components,單文件組件),但是就算你把他們拆分到多個(gè)文件中這依然會(huì)起作用。所以...我們開始吧!
集成 Typescript
我們會(huì)從 Vue CLI Webpack 模版開始,如果你使用的是非常棒的
PWA 模版,同樣可以參照本文在項(xiàng)目中添加 Typescript 支持。以下是使用 Vue CLI 初始化項(xiàng)目的指令,當(dāng)問(wèn)到是否使用 ESlint 時(shí),請(qǐng)選擇 no:
vue init webpack my-app # or: vue init pwa my-app
cd my-app
然后我們需要做4件事:
1. 在根目錄下創(chuàng)建一個(gè) tsconfig.json 文件
首先我們先做一些簡(jiǎn)單的,后面我們會(huì)回到這里做 Typescript 的配置。
{
"compilerOptions": {
"lib": ["dom", "es5", "es2015"],
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"sourceMap": true,
"allowSyntheticDefaultImports": true
}
}
在這里最重要的是 allowSyntheticDefaultImports 這個(gè)選項(xiàng)。自從 Vue types 不使用 ES2015 默認(rèn)的 exports ,這個(gè)選項(xiàng)必須要被設(shè)置為 true ??梢栽?a target="_blank" rel="nofollow"> VSCode 文檔中查看更多的信息。
選項(xiàng)"module": "es2015"將會(huì)通過(guò)編譯代碼為ESM (EcmaScript Modules) 的方式使代碼變得 tree-shakeable 。
譯者注:tree-shakeable 不知道怎么翻譯比較好,大致上就是將代碼輸出為 ES2015 的模塊,使得編譯器在編譯時(shí)能將代碼做 tree-shaking , tree-shaking 簡(jiǎn)單的來(lái)說(shuō)就是將在實(shí)際運(yùn)行過(guò)程中不運(yùn)行的代碼直接在編譯的時(shí)候移除,即 DCE, dead code elimination,常用的編譯工具中 rollup.js 和 webpack 2 / 3 都支持該項(xiàng)技術(shù),有興趣的可以查看 rollup.js 作者關(guān)于 tree-shaking 的文章
2. 添加 ts-loader 并開啟 webpack 中的選項(xiàng)
使用npm安裝 typescript 和 ts-loader:
npm i -D typescript ts-loader
然后打開 build/webpack.base.conf.js,并且在 module.rules 的開頭( vue-loader 的前面)輸入以下代碼:
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules|vue\/src/,
loader: "ts-loader",
options: {
appendTsSuffixTo: [/\.vue$/]
}
},
...
在這里,重命名入口文件的擴(kuò)展名為 .ts 并且在 extensions 中添加 .ts 的選項(xiàng)
...
entry: {
app: './src/main.ts'
},
...
resolve: {
extensions: ['.ts', '.js', '.vue', '.json'],
...
3. 添加 es-module: true 至 build/vue-loader.conf.js
這樣會(huì)使得 vue-loader 使用 ES 模塊而不是 CJS (CommonJS) 模塊,就像 vue-loader docs 中形容的那樣。
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
extract: isProduction
}),
esModule: true
}
4. 在文件中使用 Typescript
在這里你必須要做2件事情:
- 將
src文件夾下擴(kuò)展名為.js的文件的擴(kuò)展名改為.ts - 在Vue文件的
script標(biāo)簽中使用lang="ts"。比如在App.vue中:
<script lang="ts">
export default {
name: 'app'
}
</script>
問(wèn)題解析
如果你的編輯器在main.js中的import App from './App'拋出沒(méi)有找到App module的錯(cuò)誤,在項(xiàng)目中新建一個(gè)vue-shim.d.ts文件并且添加以下內(nèi)容到文件中即可解決:
declare module "*.vue" {
import Vue from 'vue'
export default Vue
}
我使用VSCode 1.13.1,并沒(méi)有看到這個(gè)問(wèn)題,而且之前也沒(méi)有(譯者使用的是VSCode 1.14.1,還是遇到了...可能是原作者使用了其他類型聲明的包)
TSLint, Prettier... 我的天!
我曾經(jīng) 在 Egghead 上錄了兩分鐘的視頻 去解釋如何無(wú)沖突的使用 TSLint 和 Prettier. 快去看吧!
譯者注:這波軟廣還是可以的,Prettier 是一個(gè)代碼格式化的工具,現(xiàn)在很多大廠都在使用,有興趣的同學(xué)可以去嘗試一下,詳情戳 Prettier 的 GitHub
OK,我現(xiàn)在可以使用 Typescript 了...那然后呢?
做到這里,Typescript 通過(guò)使用內(nèi)建的和第三方的類型已經(jīng)可以指出你的代碼里的一些你之前沒(méi)有意識(shí)到的問(wèn)題了,并且通過(guò) type 界面能夠給你一些更好的開發(fā)體驗(yàn)。就像 Slack 之前在 TypeScript at Slack 中解釋為什么要把他們的代碼庫(kù)遷移到 Typescript 中說(shuō)到的那樣。
當(dāng)然,你肯定還是需要添加你自己的類型通過(guò)UI(指UI上需要用到的數(shù)據(jù)類型)、類型、枚舉、類或者其他你需要用到類型的方式。這會(huì)讓你添加更多的 Typescript 中用于靜態(tài)類型檢查的類型,從而保證類型的安全。
理想情況下,你最好在你的 tsconfig.json 中使用 Typescript 2.3 中的 strict 編譯選項(xiàng),這將會(huì)帶來(lái)最好的類型安全。Marius Schulz 曾經(jīng)寫過(guò) 一篇很棒的文章來(lái)解釋這個(gè)問(wèn)題。在 Typescript 2.3 中,strict 模式是四個(gè)選項(xiàng)的一個(gè)組合,但是在未來(lái)可能會(huì)出現(xiàn)更多選項(xiàng):
strictNullChecksnoImplicitAnynoImplicitThisalwaysStrict
顯然,如果你有一個(gè)中大型的代碼庫(kù),使用 strict 模式將會(huì)消耗你大量的時(shí)間去解決類型缺乏的問(wèn)題。
在這種情況下,一個(gè)比較好的方法是先開啟一些比較容易修復(fù)的 Typescript 選項(xiàng),如何當(dāng)你在代碼庫(kù)中添加到一定類型覆蓋率的類型時(shí),嘗試單獨(dú)開啟一些上面提到的選項(xiàng),直到你覺(jué)得能開啟 strict 選項(xiàng)。這樣你就可以比較簡(jiǎn)單的達(dá)到你的目的了。
結(jié)尾
Typescript 從最開始就給你的代碼庫(kù)帶來(lái)了安全的類型,但是你定義的類型越多,你定位 bug 和查找錯(cuò)誤的過(guò)程就會(huì)越容易,并且這能夠讓你的代碼變得更加可靠。Vue 自從升級(jí)到2之后就添加了 typings 的支持,所以我們能夠更加容易的使用它們。這會(huì)讓OOP (Object Oriented Programming,即面向?qū)ο缶幊? 在 Vue 中發(fā)揮更大的作用,我會(huì)在其他的文章中說(shuō)到。