Vue + TypeScript 嘗鮮體驗

- 適用 Vue.version < 2.5 && Vue.version >= 2.2
其實我個人一開始很討厭 TypeScript 這個東西,就是因為討厭 Java 的啰里巴嗦,突然在我眼前出現了 JavaScript,便愛上了這門語言。
但現在的我稍稍又覺得這樣的東西其實還行,只使用類型系統也并沒有完全限制 JavaScript 本身的靈活性,并且他幫助我不會犯一些低級錯誤,而且還能配合 Visual Studio Code 的提示,我覺得這個還是很不錯的,最近忙起來的時候,甚至經常把兩個輸入框的 value 直接進行比較了,于是就想嘗試一下 TypeScript。
官方做法
Vue 2.2 以上之后,官方給 Vue已經添加了很多類型聲明,那么我們就來實踐一下在單文件 Vue 中使用 TypeScript。
1. webpack rules 中添加 ts-loader 相關(這里使用 webpack 2)
{
test: /\.ts$/,
exclude: /node_modules|vue\/src/,
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/]
}
}
表示對 .ts 文件編譯時使用 ts-loader 進行讀取,appendTsSuffixTo 是為了讓 tsc 對 vue 文件能夠當成一個 module 進行處理,以解決 moudle not found 的問題(tsc 本身不認識 vue 結尾的文件)
2. 添加 .d.ts文件
declare module "*.vue" {
import Vue from 'vue'
export default Vue
}
也是為了讓 vscode 在 ts 文件中識別 vue 結尾文件
3. 項目根目錄下添加 tsconfig.json
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"lib": [
"dom",
"es5",
"es2015.promise"
],
"module": "es2015",
"moduleResolution": "node",
"isolatedModules": false,
"target": "es5"
},
"include": [
"./src/**/*.ts"
]
}
allowSyntheticDefaultImports 是為了能夠用 es6 形式的 import,其他就參照 Vue 官網的弄了個最小化的 json。
4. 萬事俱備,讓我們 npm run dev 跑起來!
在這里,我們假設使用 Vue 官方的 webpack boilerplate,對 Hello.vue 進行一下改造。
在模板的 msg 下新增一行
<h2>Say Hello Times: {{ count }}</h2>
并將 script 部分修改成
<script lang="ts">
import Vue, { ComponentOptions } from 'vue'
// Declare the component's type
interface HelloInterface extends Vue {
msg: string,
count: number,
sayHello(): number
}
export {
HelloInterface as interface
}
export default {
data() {
return {
msg: 'Welcome to Your Vue.js App',
count: 0
}
},
methods: {
sayHello() {
this.count++;
return this.count;
}
}
// We need to explicitly annotate the exported options object
// with the Hello type
} as ComponentOptions<HelloInterface>;
</script>
這段代碼沒有什么太大的問題
接著我們改造一下 App.vue
<img src="./assets/logo.png" @click="sayHello">
<script lang="ts">
import Vue, { ComponentOptions } from 'vue';
import { interface as helloInterface, default as Hello } from './components/Hello.vue';
interface App extends Vue {
$refs: {
// 對 helloComponent 進行聲明,可以使用 helloComponent 上的方法和屬性
helloComponent: helloInterface
}
}
export default {
methods: {
sayHello() {
this.$refs.helloComponent.count++;
this.$refs.helloComponent.sayHello();
}
},
components: {
Hello
}
} as ComponentOptions<App>;
</script>
也就是說,像 refs 這種動態的在運行時才能確定的東西,如果需要在 coding 過程中靜態化,則需要在 interface 中對其進行聲明,寫的 code 稍微有點多,不過可以接受。
- 注: App.vue 修改成 lang=ts 后,頂層的 main.js 需要換成 main.ts 并修改 webpack 入口點,否則發生 file not found 錯誤
vue-class-component
官方的另一種推薦做法是 vue-class-component,不過 demo 和 readme 有點小問題,可把我這個 TypeScript 新手給難到啦,提了 pr 希望快快通過。
讓我們看看使用 vue-class-component 之后的 Hello.vue
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
@Component
export default class Hello extends Vue {
msg: string = 'Welcome to Your Vue.js App'
count: number = 0
sayHello(): number {
this.count++;
return this.count;
}
}
</script>
再讓我們看看 App.vue
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
import Hello from './components/Hello.vue';
@Component({
components: {
Hello
}
})
export default class App extends Vue {
$refs: {
helloComponent: Hello
}
sayHello() {
this.$refs.helloComponent.count++;
this.$refs.helloComponent.sayHello();
}
}
</script>
非常 Cool,非常精煉,暫時沒有想到可能會發生的沒法解決的因為 vue 或者 vue 組件 和 TypeScript 水土不服的編譯錯誤,而且都有了類型和提示。
總結
尤大佬說在接下來的 Vue 2.5 還會加強一系列的 TypeScript 支持( 鏈接 ),不知道是怎樣的支持呢。
另外,歡迎大家在評論區發表 Vue + TypeScript 的使用場景以及你遇到的錯誤。
來自:https://zhuanlan.zhihu.com/p/29971290