Vue中使用TypeScript初體驗及配置
TypeScript都比《隱祕的角落》還火,而我卻姍姍來遲的才研究他。現在來看看TS在Vue專案中的配置和一些簡單的用法,我們在單獨看TS語法的時候有些東西還是很好理解的但是在和框架(vue或react)一起使用的時候有些特殊的用法和障礙,檢視框架提供的.d.ts的宣告檔案中一些複雜型別的定義、元件的書寫方式等都要做出不小的調整。
今天沒有具體說TS是什麼怎麼用,只是簡單的學習一下TS結合框架Vue中的一些j基本用法。
Vue腳手架已經集成了TS所以在建立專案的時候可以像安裝router和Vuex似的一樣安裝TS,安裝好開啟目錄具體如下:
1 |-- ts-vue 2 |-- .browserslistrc # browserslistrc 配置檔案 (用於支援 Autoprefixer)3 |-- .eslintrc.js # eslint 配置 4 |-- .gitignore 5 |-- babel.config.js # babel-loader 配置 6 |-- package-lock.json 7 |-- package.json # package.json 依賴 8 |-- postcss.config.js # postcss 配置 9 |-- README.md 10 |-- tsconfig.json # typescript 配置11 |-- vue.config.js # vue-cli 配置 12 |-- public # 靜態資源 (會被直接複製) 13 | |-- favicon.ico # favicon圖示 14 | |-- index.html # html模板 15 |-- src 16 | |-- App.vue # 入口頁面 17 | |-- main.ts # 入口檔案 載入元件 初始化等 18 | |-- shims-tsx.d.ts19 | |-- shims-vue.d.ts 20 | |-- assets # 主題 字型等靜態資源 (由 webpack 處理載入) 21 | |-- components # 全域性元件 22 | |-- router # 路由 23 | |-- store # 全域性 vuex store 24 | |-- styles # 全域性樣式 25 | |-- views # 所有頁面 26 |-- tests # 測試
其實對比我們js的專案區別不是很大,一些js字尾的檔案被改成了ts,還多了幾個檔案
①tscinfig.json:配置檔案,主要用於指定待編譯的檔案和定義編譯選項,這個和腳手架2.x版本的congif.json一樣的作用;
②shims-tsx.s.ts:允許.tsx 結尾的檔案,在 Vue 專案中編寫 jsx 程式碼;
③shims-vue.d.ts:由於TS預設不支援匯入Vue檔案,而這個檔案就是用來識別Vue檔案。
在元件中使用TS
1.TypeScript寫元件的時候有倆種方式:Vue.extend or Vue-class-component
①Vue.extend():使用基礎 Vue 構造器,建立一個“子類”。此種寫法與 Vue 單檔案元件標準形式最為接近,唯一不同僅是元件選項需要被包裹在 Vue.extend() 中。
②vue-class-component:通常與 vue-property-decorator 一起使用,提供一系列裝飾器,能讓我們書寫類風格的 Vue 元件。
兩種形式輸出結果一致,同是建立一個 Vue 子類,但在書寫元件選項如 props,mixin 時,有些不同。特別是當你使用 Vue.extend() 時,為了讓 TypeScript 正確推斷型別,你將不得不做一些額外的處理。所以更推薦使用vue-class-component。
vue-property-decorator社群出品,但是完全依賴於vue-class-component(推薦使用這個哦)
vue-class-component官方出品,提供了Vue、Component等;
2.使用vue-property-decorator
當我們在vue
單檔案中使用TypeScript
時,引入vue-property-decorator
之後,script
中的標籤就變為這樣:
1 <script lang="ts"> 2 import {Component, Prop, Vue} from 'vue-property-decorator' 3 4 @Component({}) 5 export default class App extends Vue { 6 name:string = 'yingaxiang' 7 8 // computed 9 get MyName():string { 10 return `My name is ${this.name}` 11 } 12 13 // methods 14 sayHello():void { 15 alert(`Hello ${this.name}`) 16 } 17 18 mounted() { 19 this.sayHello(); 20 } 21 } 22 </script>
等同於js中的
1 <script lang="es6"> 2 export default { 3 data () { 4 return { 5 name: 'yingaxiang' 6 } 7 }, 8 9 mounted () { 10 this.sayHello() 11 }, 12 13 computed: { 14 MyName() { 15 return `My name is ${this.name}` 16 } 17 }, 18 19 methods: { 20 sayHello() { 21 alert(`Hello ${this.name}`) 22 }, 23 } 24 } 25 </script>
小結:
①@component宣告成一個vue的元件例項,如果不使用則不能得到一個vue元件,所以這個無論有沒有引入自定義元件都要宣告,和js的components有些區別;
②vue中的計算屬性,我們只需要將該計算屬性名定義為為一個函式,並在在函式之前加上get關鍵字就可,所以原本寫在computed中的計算屬性現在只要在前邊加上get。
3.在vue-class-decorator中還有其他屬性下邊詳解
①@Emit:在Vue的事件監聽與觸發子父傳參中都要用到$emit和$on,那麼在 vue-property-decorator中提供了@Emit
1 <script lang="ts"> 2 import {Vue, Component, Emit} from 'vue-property-decorator'; 3 4 @Component({}) 5 export default class "元件名" extends Vue{ 6 mounted(){ 7 this.$on('emit-todo', function(n) { 8 console.log(n) 9 }) 10 11 this.emitTodo('yingaxiang'); 12 } 13 14 @Emit() 15 emitTodo(n: string){ 16 console.log('yingaxiang'); 17 } 18 } 19 </script>
等同於js中:
1 <script lang="es6"> 2 import Vue from 'vue'; 3 4 export default { 5 mounted(){ 6 this.$on('emit-todo', function(n) { 7 console.log(n) 8 }) 9 10 this.emitTodo('yingaxiang'); 11 }, 12 methods: { 13 emitTodo(n){ 14 console.log('yingaxiang'); 15 this.$emit('emit-todo', n); 16 } 17 } 18 } 19 </script>
小結:
在Vue
中我們是使用$emit
觸發事件,使用vue-property-decorator
時,可以藉助@Emit
裝飾器來實現.@Emit
修飾的函式所接受的引數會在執行之後觸發事件的時候傳遞過去。@Emit觸發事件有倆種寫法:
@Emit()
不傳引數,那麼它觸發的事件名就是它所修飾的函式名.
@Emit(name: string)
,裡面傳遞一個字串,該字串為要觸發的事件名.
②利用vue-property-decorator
提供的@Watch
裝飾器來替換Vue
中的watch
屬性,以此來監聽值的變化.
1 <script lang="ts"> 2 import {Vue, Component, Watch} from 'vue-property-decorator';、 3 @Watch('child') 4 onChangeValue(newVal: string, oldVal: string){ 5 // todo... 6 } 7 8 @Watch('person', {immediate: true, deep: true}) 9 onChangeValue(newVal: Person, oldVal: Person){ 10 // todo... 11 } 12 </script>
等同於js中
1 export default{ 2 watch: { 3 'child': this.onChangeValue 4 // 這種寫法預設 `immediate`和`deep`為`false` 5 , 6 'person': { 7 handler: 'onChangeValue', 8 immediate: true, 9 deep: true 10 } 11 }, 12 methods: { 13 onChangeValue(newVal, oldVal){ 14 // todo... 15 } 16 } 17 }
③@prop屬性子元件接收父元件傳遞來的引數.我們需要定義Prop
屬性.
1 <script lang="ts"> 2 import {Vue, Component, Prop} from 'vue-property-decorator'; 3 4 @Component({}) 5 export default class "元件名" extends Vue{ 6 @Prop(Number) propA!: number; 7 @Prop({default: 'default value'}) propB!: string; 8 @propC([String, Boolean]) propC: string | boolean; 9 } 10 </script>
等同於js的:
1 export default { 2 props: { 3 propA: { 4 type: Number 5 }, 6 propB: { 7 default: 'default value' 8 }, 9 propC: { 10 type: [String, Boolean] 11 }, 12 } 13 }
這裡需要特別強調:
!: 表示一定存在,?: 表示可能不存在。這兩種在語法上叫賦值斷言
以上介紹應該是TS在vue中最基本的使用方式,持續學習中......