Vue.js TypeScript 支援
TypeScript 支援
在 Vue 2.5.0 中,我們大大改進了型別宣告以更好地使用預設的基於物件的 API。同時此版本也引入了一些其它變化,需要開發者作出相應的升級。閱讀部落格文章瞭解更多詳情。
釋出為 NPM 包的官方宣告檔案
靜態型別系統能幫助你有效防止許多潛在的執行時錯誤,而且隨著你的應用日漸豐滿會更加顯著。這就是為什麼 Vue 不僅僅為 Vue core 提供了針對 TypeScript 的官方型別宣告,還為 Vue Router 和 Vuex 也提供了相應的宣告檔案。
而且,我們已經把它們釋出到了 NPM
推薦配置
// tsconfig.json { "compilerOptions": { // 與 Vue 的瀏覽器支援保持一致 "target": "es5", // 這可以對 `this` 上的資料屬性進行更嚴格的推斷 "strict": true, // 如果使用 webpack 2+ 或 rollup,可以利用 tree-shake: "module": "es2015", "moduleResolution": "node" } } |
注意你需要引入 strict: true
(或者至少 noImplicitThis: true
,這是 strict
模式的一部分) 以利用元件方法中 this
的型別檢查,否則它會始終被看作 any
型別。
參閱 TypeScript 編譯器選項文件 (英) 瞭解更多。
開發工具鏈
工程建立
Vue CLI 3 可以使用 TypeScript 生成新工程。建立方式:
# 1. 如果沒有安裝 Vue CLI 就先安裝 npm install --global @vue/cli # 2. 建立一個新工程,並選擇 "Manually select features (手動選擇特性)" 選項 vue create my-project-name |
編輯器支援
要使用 TypeScript 開發 Vue 應用程式,我們強烈建議您使用 Visual Studio Code,它為 TypeScript 提供了極好的“開箱即用”支援。如果你正在使用單檔案元件 (SFC), 可以安裝提供 SFC 支援以及其他更多實用功能的 Vetur 外掛。
WebStorm 同樣為 TypeScript 和 Vue 提供了“開箱即用”的支援。
基本用法
要讓 TypeScript 正確推斷 Vue 元件選項中的型別,您需要使用 Vue.component
或 Vue.extend
定義元件:
import Vue from 'vue' const Component = Vue.extend({ // 型別推斷已啟用 }) const Component = { // 這裡不會有型別推斷, // 因為TypeScript不能確認這是Vue元件的選項 } |
基於類的 Vue 元件
如果您在宣告元件時更喜歡基於類的 API,則可以使用官方維護的 vue-class-component 裝飾器:
import Vue from 'vue' import Component from 'vue-class-component' // @Component 修飾符註明了此類為一個 Vue 元件 @Component({ // 所有的元件選項都可以放在這裡 template: '<button @click="onClick">Click!</button>' }) export default class MyComponent extends Vue { // 初始資料可以直接宣告為例項的屬性 message: string = 'Hello!' // 元件方法也可以直接宣告為例項的方法 onClick (): void { window.alert(this.message) } } |
增強型別以配合外掛使用
外掛可以增加 Vue 的全域性/例項屬性和元件選項。在這些情況下,在 TypeScript 中製作外掛需要型別宣告。慶幸的是,TypeScript 有一個特性來補充現有的型別,叫做模組補充 (module augmentation)。
例如,宣告一個 string
型別的例項屬性 $myProperty
:
// 1. 確保在宣告補充的型別之前匯入 'vue' import Vue from 'vue' // 2. 定製一個檔案,設定你想要補充的型別 // 在 types/vue.d.ts 裡 Vue 有建構函式型別 declare module 'vue/types/vue' { // 3. 宣告為 Vue 補充的東西 interface Vue { $myProperty: string } } |
在你的專案中包含了上述作為宣告檔案的程式碼之後 (像 my-property.d.ts
),你就可以在 Vue 例項上使用 $myProperty
了。
var vm = new Vue() console.log(vm.$myProperty) // 將會順利編譯通過 |
你也可以宣告額外的屬性和元件選項:
import Vue from 'vue' declare module 'vue/types/vue' { // 可以使用 `VueConstructor` 介面 // 來宣告全域性屬性 interface VueConstructor { $myGlobal: string } } // ComponentOptions 聲明於 types/options.d.ts 之中 declare module 'vue/types/options' { interface ComponentOptions<V extends Vue> { myOption?: string } } |
上述的宣告允許下面的程式碼順利編譯通過:
// 全域性屬性 console.log(Vue.$myGlobal) // 額外的元件選項 var vm = new Vue({ myOption: 'Hello' }) |
標註返回值
因為 Vue 的宣告檔案天生就具有迴圈性,TypeScript 可能在推斷某個方法的型別的時候存在困難。因此,你可能需要在 render
或 computed
裡的方法上標註返回值。
import Vue, { VNode } from 'vue' const Component = Vue.extend({ data () { return { msg: 'Hello' } }, methods: { // 需要標註有 `this` 參與運算的返回值型別 greet (): string { return this.msg + ' world' } }, computed: { // 需要標註 greeting(): string { return this.greet() + '!' } }, // `createElement` 是可推導的,但是 `render` 需要返回值型別 render (createElement): VNode { return createElement('div', this.greeting) } }) |
如果你發現型別推導或成員補齊不工作了,標註某個方法也許可以幫助你解決這個問題。使用 --noImplicitAny
選項將會幫助你找到這些未標註的方法。