1. 程式人生 > 實用技巧 >Vue中使用TypeScript初體驗及配置

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.ts
19 | |-- 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中最基本的使用方式,持續學習中......