最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解在Vue中使用TypeScript的一些思考(實踐)

 更新時間:2018年07月06日 09:17:13   作者:三毛  
這篇文章主要介紹了詳解在Vue中使用TypeScript的一些思考(實踐),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

Vue.extend or vue-class-component

使用 TypeScript 寫 Vue 組件時,有兩種推薦形式:

  • Vue.extend():使用基礎 Vue 構(gòu)造器,創(chuàng)建一個“子類”。此種寫法與 Vue 單文件組件標準形式最為接近,唯一不同僅是組件選項需要被包裹在 Vue.extend() 中。
  • vue-class-component:通常與 vue-property-decorator 一起使用,提供一系列裝飾器,能讓我們書寫類風格的 Vue 組件。

兩種形式輸出結(jié)果一致,同是創(chuàng)建一個 Vue 子類,但在書寫組件選項如 props,mixin 時,有些不同。特別是當你使用 Vue.extend() 時,為了讓 TypeScript 正確推斷類型,你將不得不做一些額外的處理。接下來,我們來聊一聊它們的細節(jié)差異。

Prop

由于組件實例的作用域是孤立的,當從父組件傳遞數(shù)據(jù)到子組件時,我們通常使用 Prop 選項。同時,為了確保 Prop 的類型安全,我們會給 Prop 添加指定類型驗證,形式如下:

export default {
 props: {
  someProp: {
   type: Object,
   required: true,
   default: () => ({ message: 'test' })
  }
 }
}

我們定義了一個 someProp,它的類型是 Object。

使用 JavaScript 時,這并沒有什么不對的地方,但當你使用 TypeScript 時,這有點不足,我們并不能得到有關于 someProp 更多有用的信息(比如它含有某些屬性),甚至在 TypeScript 看來,這將會是一個 any 類型:

這意味著我們可以使用 someProp 上的任意屬性(存在或者是不存在的)都可以通過編譯。為了防止此種情況的發(fā)生,我們將會給 Prop 添加類型注釋。

Vue.extend()

使用 Vue.extend() 方法添加類型注釋時,需要給 type 斷言:

import Vue from 'vue'

interface User {
 name: string,
 age: number
}

export default Vue.extend({
 props: {
  testProps: {
   type: Object as () => User
  }
 }
})

當組件內(nèi)訪問 testProps 時,便能得到相關提示:

然而,你必須以函數(shù)返回值的形式斷言,并不能直接斷言:

export default Vue.extend({
 props: {
  testProps: {
   type: Object as User
  }
 }
})

它會給出錯誤警告,User 接口并沒有實現(xiàn)原生 Object 構(gòu)造函數(shù)所執(zhí)行的方法:
Type 'ObjectConstructor' cannot be converted to type 'User'. Property 'id' is missing in type 'ObjectConstructor'.

實際上,我們可從 Prop type declaration

export type Prop<T> = { (): T } | { new (...args: any[]): T & object }

export type PropValidator<T> = PropOptions<T> | Prop<T> | Prop<T>[];

export interface PropOptions<T=any> {
 type?: Prop<T> | Prop<T>[];
 required?: boolean;
 default?: T | null | undefined | (() => object);
 validator?(value: T): boolean;
}

可知 Prop type 可以以兩種不同方式出現(xiàn):

  • 含有一個調(diào)用簽名的范型 type,該簽名返回 T;
  • 一個范型構(gòu)造函數(shù)簽名,該函數(shù)創(chuàng)建指定類型 T 對象 (返回值 T & object 用于降低優(yōu)先級,當兩種方式同時滿足時取第一種,其次它還可以用于標記構(gòu)造函數(shù)不應該返回原始類型)。

當我們指定 type 類型為 String/Number/Boolean/Array/Object/Date/Function/Symbol 等原生構(gòu)造函數(shù)時,Prop<T> 會返回它們各自簽名的返回值。

當 type 類型為 String 構(gòu)造函數(shù)時,它的調(diào)用簽名返回為 string:

// lib.es5.d.ts

interface StringConstructor {
 new(value?: any): String;
 (value?: any): string;
 readonly prototype: String;
 fromCharCode(...codes: number[]): string;
}

而這也是上文中,當指定 type 類型為 Object 構(gòu)造函數(shù)時,經(jīng)過 Vue 的聲明文件處理,TypeScript 推斷出為 any 類型的原因:

interface ObjectConstructor {
 new(value?: any): Object;
 (): any;
 (value: any): any;
 // 其它屬性 ....
}

類似的,當我們使用關鍵字 as 斷言 Object 為 () => User 時,它能推斷出為 User 。

從 type 第二部分可知,除傳入原生構(gòu)造函數(shù)外,我們還可傳入自定義類:

此外,這里有個 PR 暴露一個更直觀的類型( Vue 2.6 版本才可以用):

props: {
 testProp: Object as PropTypes<{ test: boolean }>
}

vue-class-component

得益于 vue-propperty-decorator Prop 修飾器,當給 Prop 增加類型推斷時,這些將變得簡單:

import { Component, Vue, Prop } from 'vue-property-decorator'

@Component
export default class Test extends Vue {
 @Prop({ type: Object })
 private test: { value: string }
}

當我們在組件內(nèi)訪問 test 時,便能獲取它正確的類型信息。

mixins

mixins 是一種分發(fā) Vue 組件中可復用功能的一種方式。當在 TypeScript 中使用它時,我們希望得到有關于 mixins 的類型信息。

當你使用 Vue.extends() 時,這有點困難,它并不能推斷出 mixins 里的類型:

// ExampleMixin.vue
export default Vue.extend({
 data () {
  return {
   testValue: 'test'
  }
 }
})

// other.vue
export default Vue.extend({
 mixins: [ExampleMixin],
 created () {
  this.testValue // error, testValue 不存在!
 }
})

我們需要稍作修改:

// other.vue
export default ExampleMixin.extend({
 mixins: [ExampleMixin],
 created () {
  this.testValue // 編譯通過
 }
})

但這會存在一個問題,當使用多個 mixins 且推斷出類型時,這將無法工作。而在這個 Issuse 中官方也明確表示,這無法被修改。

使用 vue-class-component 這會方便很多:

// ExampleMixin.vue
import Vue from 'vue'
import Component from 'vue-class-component'

@Component
export class ExampleMixin extends Vue {
 public testValue = 'test'
}

// other.vue
import Component, { mixins } from 'vue-class-component'
import ExampleMixin from 'ExampleMixin.vue'

@Component({
 components: {
  ExampleMixin
 }
})
export class MyComp extends mixins(ExampleMixin) {
 created () {
  console.log(this.testValue) // 編譯通過
 }
}

也支持可以傳入多個 mixins。

一些其它

做為 Vue 中最正統(tǒng)的方法(與標準形式最為接近),Vue.extends() 有著自己的優(yōu)勢,在 VScode Vetur 插件輔助下,它能正確提示子組件上的 Props:

而類做為 TypeScript 特殊的存在(它既可以作為類型,也可以作為值),當我們使用 vue-class-component 并通過 $refs 綁定為子類組件時,便能獲取子組件上暴露的類型信息:

導入 .vue 時,為什么會報錯?

當你在 Vue 中使用 TypeScript 時,所遇到的第一個問題即是在 ts 文件中找不到 .vue 文件,即使你所寫的路徑并沒有問題:

在 TypeScript 中,它僅識別 js/ts/jsx/tsx 文件,為了讓它識別 .vue 文件,我們需要顯式告訴 TypeScript,vue 文件存在,并且指定導出 VueConstructor:

declare module '*.vue' {
 import Vue from 'vue'
 export default Vue
}

但是,這引起了另一個問題,當我們導入一個并不存在的 .vue 文件時,也能通過編譯:

是的,這在情理之中。

當我嘗試在 .vue 文件中導入已存在或者不存在的 .vue 文件時,卻得到不同的結(jié)果:

文件不存在時:

文件存在時:

文件不存在時,引用 Vue 的聲明文件。文件存在時,引用正確的文件定義。

這讓人很困惑,而這些都是 Vetur 的功勞。

在這個 PR 下,我找到相關解答:這個 PR 里,Vetur 提供解析其他 .vue 文件的功能,以便能獲取正確的信息,當 .vue 文件不存在時,會讀取 .d.ts 里的信息。

參考

https://github.com/vuejs/vue/pull/5887

https://github.com/vuejs/vue/issues/7211

https://github.com/vuejs/vue/pull/6856

https://github.com/vuejs/vue/pull/5887/files/1092efe6070da2052a8df97a802c9434436eef1e#diff-23d7799dcc9e9be419d28a15348b0d99

https://github.com/Microsoft/TypeScript/blob/8e47c18636da814117071a2640ccf87c5f16fcfd/src/compiler/types.ts#L3563-L3583

https://github.com/vuejs/vetur/pull/94

相關文章

  • Vue?如何關掉響應式問題

    Vue?如何關掉響應式問題

    這篇文章主要介紹了Vue?如何關掉響應式問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue實現(xiàn)隨機驗證碼功能的實例代碼

    vue實現(xiàn)隨機驗證碼功能的實例代碼

    這篇文章主要介紹了vue實現(xiàn)隨機驗證碼功能的實例代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-04-04
  • Vue中組件遞歸及使用問題

    Vue中組件遞歸及使用問題

    這篇文章主要介紹了Vue中組件的遞歸和使用問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • vue項目啟動后沒有局域網(wǎng)地址問題

    vue項目啟動后沒有局域網(wǎng)地址問題

    這篇文章主要介紹了vue項目啟動后沒有局域網(wǎng)地址問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Vue模板語法v-bind教程示例

    Vue模板語法v-bind教程示例

    這篇文章主要為大家介紹了Vue模板語法v-bind教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • Vue實現(xiàn)簡單跑馬燈特效

    Vue實現(xiàn)簡單跑馬燈特效

    這篇文章主要為大家詳細介紹了Vue實現(xiàn)簡單跑馬燈特效,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 在vue3中使用el-tree-select實現(xiàn)樹形下拉選擇器效果

    在vue3中使用el-tree-select實現(xiàn)樹形下拉選擇器效果

    el-tree-select是一個含有下拉菜單的樹形選擇器,結(jié)合了?el-tree?和?el-select?兩個組件的功能,這篇文章主要介紹了在vue3中使用el-tree-select做一個樹形下拉選擇器,需要的朋友可以參考下
    2024-03-03
  • VUE簽字組件vue-esign安裝使用教程

    VUE簽字組件vue-esign安裝使用教程

    在我們開發(fā)項目中,特別是流程審批類的項目,最后一步會提交審核,審核員看完相應信息以后,沒問題就會簽字通過審批,這篇文章主要給大家介紹了關于VUE簽字組件vue-esign安裝使用的相關資料,需要的朋友可以參考下
    2023-09-09
  • vue項目實現(xiàn)點擊目標區(qū)域之外可關閉(隱藏)目標區(qū)域

    vue項目實現(xiàn)點擊目標區(qū)域之外可關閉(隱藏)目標區(qū)域

    這篇文章主要介紹了vue項目實現(xiàn)點擊目標區(qū)域之外可關閉(隱藏)目標區(qū)域,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • vue3通過組合鍵實現(xiàn)換行操作的示例詳解

    vue3通過組合鍵實現(xiàn)換行操作的示例詳解

    這篇文章主要為大家詳細介紹了vue3如何通過組合鍵,例如command+Enter、shift+Enter、alt + Enter,實現(xiàn)換行操作,感興趣的可以了解下
    2024-03-03

最新評論

永寿县| 双鸭山市| 重庆市| 武强县| 奈曼旗| 陇西县| 手游| 鲁山县| 怀远县| 石楼县| 万宁市| 手游| 平潭县| 肇源县| 泽库县| 修文县| 海城市| 临高县| 巴林左旗| 西昌市| 萍乡市| 祥云县| 阳信县| 金昌市| 凤台县| 郴州市| 高要市| 临城县| 永城市| 高青县| 乐昌市| 沙洋县| 英山县| 鄱阳县| 苍梧县| 灵川县| 龙山县| 莱芜市| 漳州市| 平远县| 延吉市|