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

詳解Vue2.5+遷移至Typescript指南

 更新時(shí)間:2019年08月01日 08:30:55   作者:coderAfei  
這篇文章主要介紹了詳解Vue2.5+遷移至Typescript指南,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

為什么要遷移至Typescript

Javascript本身是動(dòng)態(tài)弱類(lèi)型的語(yǔ)言,這樣的特點(diǎn)導(dǎo)致了Javascript代碼中充斥著很多Uncaught TypeError的報(bào)錯(cuò),給開(kāi)發(fā)調(diào)試和線上代碼穩(wěn)定都帶來(lái)了不小的負(fù)面影響。

而Typescript提供了靜態(tài)類(lèi)型檢查,使很多類(lèi)型錯(cuò)誤在編寫(xiě)時(shí)就已經(jīng)發(fā)現(xiàn),不會(huì)帶到測(cè)試階段。

同時(shí),Javascript不定義model就可以使用一個(gè)對(duì)象,有人喜歡這樣的靈活性,的確這樣的語(yǔ)法在model不復(fù)雜的時(shí)候可以快速的開(kāi)發(fā)出需要的功能,但一旦model龐大,找一個(gè)需要的屬性值都不知道從何找起。而在Typescript中,我們需要使用TS中的interface type等方式先定義出model,才可以調(diào)用其屬性值,所以Typescript極大的提高了代碼的可讀性。

可行性

因?yàn)門(mén)ypeScript是JavaScript的超集,TypeScript 不會(huì)阻止 JavaScript 的運(yùn)行,即使存在類(lèi)型錯(cuò)誤也不例外,這能讓你的 JavaScript 逐步遷移至 TypeScript。所以可以慢慢地做遷移,一次遷移一個(gè)模塊,選擇一個(gè)模塊,重命名.js文件到.ts,在代碼中添加類(lèi)型注釋。當(dāng)你完成這個(gè)模塊時(shí),選擇下一個(gè)模塊。

如何將已有的Vue項(xiàng)目遷移至Typescript

安裝依賴(lài)

Vue官方提供了一個(gè)庫(kù)Vue-class-component,用于讓我們使用Ts的類(lèi)聲明方式來(lái)編寫(xiě)vue組件代碼。Vue-property-decorator則是在Vue-class-component的基礎(chǔ)上提供了裝飾器的方式來(lái)編寫(xiě)代碼。首先我們需要在package.json中引入這兩個(gè)依賴(lài)。

我的項(xiàng)目是基于vue-cli@3.X創(chuàng)建的,還需要在項(xiàng)目中引入@vue/cli-plugin-typescript typescript兩個(gè)依賴(lài)來(lái)完成Typescript的編譯。

配置tsconfig.json

在項(xiàng)目根目錄新建tsconfig.json,并引入以下代碼

{
 "compilerOptions": {
  "target": "esnext",
  "module": "esnext",
  "strict": true,
  "jsx": "preserve",
  "importHelpers": true,
  "moduleResolution": "node",
  "experimentalDecorators": true,
  "esModuleInterop": true,
  "allowSyntheticDefaultImports": true,
  "sourceMap": true,
  "baseUrl": ".",
  "noFallthroughCasesInSwitch":true,
  "noImplicitAny":true,
  "noImplicitReturns":true,
  "noImplicitThis":true,
  "types": [
   "webpack-env"
  ],
  "paths": {
   "@/*": [
    "./app/common/*"
   ],
   "_app/*": [
    "./app/*"
   ],
   "_c/*": [
    "./app/common/components/*"
   ],
   "api/*": [
    "./app/service/*"
   ],
   "assets/*": [
    "./app/assets/*"
   ]
  },
  "lib": [
   "esnext",
   "dom",
   "dom.iterable",
   "scripthost"
  ],
 },
 "include": [   // 在此出填寫(xiě)你的項(xiàng)目中需要按照typescript編譯的文件路徑
  "app/**/*.ts",
  "app/**/*.tsx",
  "app/**/*.d.ts",
  "app/**/*.vue",
 ],
 "exclude": [
  "node_modules"
 ]
}

特別需要注意的是,現(xiàn)在的vue項(xiàng)目中大多使用了webpack的alias來(lái)解析路徑,在tsconfig.json中需要配置path屬性,讓typescript同樣認(rèn)識(shí)在webpack中配置的路徑別名。

添加全局聲明文件

因?yàn)樵趖s文件中是無(wú)法識(shí)別vue文件的,所以需要在項(xiàng)目根目錄新建shims-vue.d.ts文件,添加以下代碼,來(lái)讓ts識(shí)別vue文件。

import Vue from 'vue';

declare module '*.vue' {
 export default Vue;
}

由下而上的遷移

因?yàn)槭沁w移已經(jīng)存在的項(xiàng)目,不建議開(kāi)始就把main.js重命名為main.ts,對(duì)于絕大多數(shù)Vue項(xiàng)目,main.js引入了太多的依賴(lài),我們應(yīng)該首先從依賴(lài)著手,自下而上的遷移Typescript。對(duì)于項(xiàng)目中一些偏底層,甚至是框架維護(hù)者所提供的庫(kù)函數(shù),我們不關(guān)心其實(shí)現(xiàn)邏輯,所以沒(méi)有必要將其改寫(xiě)為ts文件,只需要給其加聲明文件供我們的業(yè)務(wù)代碼調(diào)用即可。

在我的項(xiàng)目中,service層的邏輯非常簡(jiǎn)單,僅僅是傳參數(shù)調(diào)用接口,沒(méi)有添加任何其他的邏輯,邏輯如此簡(jiǎn)單其實(shí)沒(méi)有什么必要改寫(xiě)為ts文件,所以我為service層的文件編寫(xiě)聲明文件,來(lái)為調(diào)用service層的代碼提供類(lèi)型聲明。

聲明文件編寫(xiě)方法

一個(gè)js文件如下

//service.js
import axios from '@/libs/api.request'
export default {
  /**
   * 創(chuàng)建賬戶(hù)
   * @param {Object} data
   * @param {String} data.accountType optinal
   * @param {String} data.username
   * @param {String} data.password
   * @param {String} data.gender X | F | M
   * @param {String} data.email
   * @param {Number} data.level
   */

  createAccount(data) {
    return axios.request({
      url: `/api/account/createUser`,
      method: 'post',
      data: data
    }).then((res) => [res, null]).catch((err) => [null, err]);
  },
}

可以看到,在使用typescript之前,對(duì)于一個(gè)函數(shù)的參數(shù)和返回值等信息的提示是通過(guò)jsdoc實(shí)現(xiàn)的,能夠在調(diào)用時(shí)確定參數(shù)類(lèi)型及名稱(chēng),但jsdoc畢竟只是注釋?zhuān)⒉荒芴峁╊?lèi)型校驗(yàn),所以在這里我們?yōu)槠渚帉?xiě)聲明文件,編寫(xiě)后的聲明文件如下

//service.d.ts
interface createAccountParams {
  accountType?: string,
  username: string,
  password: string,
  gender: 'X' | 'F' | 'M',
  email: string,
  level?: number
}
interface createAccountReturn {
  userId: string,
}
export interface Service {
  createAccount(data: createAccountParams): createAccountReturn
}

這樣一個(gè)service層的接口文件的聲明文件就編寫(xiě)完成了,為了獲得Typescript和vscode提供的類(lèi)型提示和校驗(yàn),在main.js中將service.js導(dǎo)出的實(shí)例綁定在了Vue原型上,使得我們可以在vue組件中通過(guò)vm.$service方便的訪問(wèn)service實(shí)例。但是Typescript并不知道Vue實(shí)例上有什么屬性,這時(shí)需要我們?cè)谥疤砑拥膕hims-vue.d.ts文件中添加幾行代碼。

import Vue from 'vue';
import Service from "pathToService/service.d.ts";

declare module '*.vue' {
 export default Vue;
}

declare module "vue/types/vue" {
 interface Vue {
  $service: Service
 }
}

得力于typescript中提供的模塊補(bǔ)充功能,我們可以在node_modules/vue/types/vue中補(bǔ)充我們需要在Vue上提供的屬性。

改寫(xiě)Vue文件

我們需要將原來(lái)的vue文件改寫(xiě)成使用vue-property-decorator編寫(xiě)的方式。

<script lang="ts">
import {Component,Vue} from "vue-property-decorator";

@Component
export default class MyComponent extends Vue{
  // 聲明data
  form: {
    accountType?: string,
    username: string,
    password: string,
    gender: 'X' | 'F' | 'M',
    email: string,
    level?: number
  } = {
    username:'',
    password:'',
    gender:'X',
    email:''
  };

  // 聲明methods
  async submit(): void {
    //調(diào)用上面的service接口
    const [res,err] = await this.$service.createAccount(this.form);
  }
}
</script>

至此一個(gè)Vue項(xiàng)目遷移至Typescript的過(guò)程就已經(jīng)完成了,剩下的工作就是將代碼中其他的文件一步步由js遷移到typescript中。

把方法綁定到Vue實(shí)例下

除了我們之前提到過(guò)的將自己編寫(xiě)的service掛載到vue實(shí)例上,大家一定清楚在vue項(xiàng)目中,我們經(jīng)常會(huì)調(diào)用this.$refs this.$router this.$store等等,typescript也會(huì)檢查這些屬性是否被綁定在了vue實(shí)例上,那么我們并沒(méi)有在類(lèi)型系統(tǒng)中聲明這些值,按道理應(yīng)該報(bào)Property '$refs' does not exist on type [your_component_name]
真相是vue vue-router vuex都已經(jīng)給我們聲明了相應(yīng)的類(lèi)型,我們可以cd ./node_modules/vue/types/目錄中去查看
截取少量代碼如下所示:

export interface Vue {
 readonly $el: Element;
 readonly $options: ComponentOptions<Vue>;
 readonly $parent: Vue;
 readonly $root: Vue;
 readonly $children: Vue[];
 readonly $refs: { [key: string]: Vue | Element | Vue[] | Element[] };
 readonly $slots: { [key: string]: VNode[] | undefined };
 readonly $scopedSlots: { [key: string]: NormalizedScopedSlot | undefined };
 readonly $isServer: boolean;
 readonly $data: Record<string, any>;
 readonly $props: Record<string, any>;
 readonly $ssrContext: any;
 readonly $vnode: VNode;
 readonly $attrs: Record<string, string>;
 readonly $listeners: Record<string, Function | Function[]>;
}

只要正常的在依賴(lài)中安裝了vue-router vuex就已經(jīng)通過(guò)模塊補(bǔ)充的方式將類(lèi)型添加到了vue實(shí)例上。

在一些項(xiàng)目中,vue-router vuex這些依賴(lài)不是通過(guò)安裝在依賴(lài)中引入的,而是通過(guò)index.html引入的cdn資源文件,這樣在開(kāi)發(fā)過(guò)程中我們就無(wú)法獲取其類(lèi)型。

這個(gè)時(shí)候我們可以通過(guò)安裝@types依賴(lài)的方式將類(lèi)型系統(tǒng)補(bǔ)充到項(xiàng)目中,如npm install @types/jquery --save-dev。

不幸的是vue-router和vuex的types包已經(jīng)廢棄了,只能通過(guò)手動(dòng)去github上下載對(duì)應(yīng)版本的vue-router vuex將types文件引入到項(xiàng)目中,你可以像我一樣在項(xiàng)目中新建一個(gè)types目錄,引入需要的類(lèi)型聲明文件。

這樣就可以直接在vue實(shí)例上訪問(wèn)到$store $router等屬性了。

同理當(dāng)你想要引入其他的組件庫(kù)上的一些類(lèi)型文件時(shí),也是這樣的方式。

一些需要注意的問(wèn)題

在vue開(kāi)發(fā)過(guò)程中我們會(huì)使用this.$refs去訪問(wèn)某一個(gè)具體實(shí)例的方法,但是這在ts中是訪問(wèn)不到的常見(jiàn)的,比如要想要使用form組件中的validate方法,我們需要給其加上類(lèi)型斷言
this.$refs.form.validate()變?yōu)?code>(this.$refs.form as Vue & {validate:Function}).validate()
來(lái)告訴編譯器this.$refs.form上有validate方法。

因?yàn)轭?lèi)型斷言前提條件是是當(dāng) S 類(lèi)型是 T 類(lèi)型的子集,或者 T 類(lèi)型是 S 類(lèi)型的子集時(shí),S 能被成功斷言成 T,所以需要在類(lèi)型斷言時(shí)合并Vue類(lèi)型。

同時(shí)也可以通過(guò)vue-property-decorator提供給我們的裝飾器一勞永逸的將該refs添加到computed屬性上

import { Vue, Component, Ref } from 'vue-property-decorator'
import Form from '@/path/to/another-component.vue'
@Component
export default class YourComponent extends Vue {
 @Ref() readonly form!: Form
}

等同于

export default {
 computed() {
  form: {
   cache: false,
   get() {
    return this.$refs.form as Form
   }
  },
 }
}

這樣我們就可以通過(guò) this.form.validate()來(lái)做表單校驗(yàn)了

新手容易遇到的一些問(wèn)題

疑問(wèn)1:interface和type有什么區(qū)別?

type 可以聲明基本類(lèi)型別名,聯(lián)合類(lèi)型,元組等類(lèi)型

eg.type a = string;是被允許的,

interface 會(huì)自動(dòng)聲明合并

interface person{
  gender:string
  age:number
}
interface person{
  name:string
}

疑問(wèn)2: 錯(cuò)誤 Property 'hideContent' has no initializer and is not definitely assigned in the constructor.

strictPropertyInitialization屬性會(huì)在strict設(shè)置為true時(shí)自動(dòng)被設(shè)置為true。

但這個(gè)屬性并不合理,它要求每個(gè)實(shí)例的屬性都有初始值,我們?cè)趖sconfig將其設(shè)置為false就好了。

疑問(wèn)3: 賦值兼容性

interface person {
  name:string
  age:number
}
interface student {
  name:string
  age:number
  stuid:string
}
let person: person= {
  name:'name',
  age:1
}
let student: student = {
  name:'name',
  age:1,
  stuid:'stuid'
};

person = student //這樣是可以的
student = person //這樣不允許

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue組件之非單文件組件的使用詳解

    Vue組件之非單文件組件的使用詳解

    Vue中常常會(huì)把組件分為非單文件組件和單文件組件,這篇文章主要為大家介紹了非單文件組件的具體使用方法,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2023-05-05
  • 淺談vue項(xiàng)目4rs vue-router上線后history模式遇到的坑

    淺談vue項(xiàng)目4rs vue-router上線后history模式遇到的坑

    今天小編就為大家分享一篇淺談vue項(xiàng)目4rs vue-router上線后history模式遇到的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • vue?循環(huán)動(dòng)態(tài)設(shè)置ref并獲取$refs方式

    vue?循環(huán)動(dòng)態(tài)設(shè)置ref并獲取$refs方式

    這篇文章主要介紹了vue?循環(huán)動(dòng)態(tài)設(shè)置ref并獲取$refs方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Vue3中ref與toRef的區(qū)別淺析

    Vue3中ref與toRef的區(qū)別淺析

    我們知道ref可以用于創(chuàng)建一個(gè)響應(yīng)式數(shù)據(jù),而toRef也可以創(chuàng)建一個(gè)響應(yīng)式數(shù)據(jù),這篇文章主要給大家介紹了關(guān)于Vue3中ref與toRef區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • vux uploader 圖片上傳組件的安裝使用方法

    vux uploader 圖片上傳組件的安裝使用方法

    這篇文章主要介紹了vux-uploader 圖片上傳組件的安裝及使用方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-05-05
  • 基于ant-design-vue實(shí)現(xiàn)表格操作按鈕組件

    基于ant-design-vue實(shí)現(xiàn)表格操作按鈕組件

    這篇文章主要為大家介紹了基于ant-design-vue實(shí)現(xiàn)表格操作按鈕組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Vue2.X和Vue3.0數(shù)據(jù)響應(yīng)原理變化的區(qū)別

    Vue2.X和Vue3.0數(shù)據(jù)響應(yīng)原理變化的區(qū)別

    這篇文章主要介紹了Vue2.X和Vue3.0數(shù)據(jù)響應(yīng)原理變化的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • element-ui 表格實(shí)現(xiàn)單元格可編輯的示例

    element-ui 表格實(shí)現(xiàn)單元格可編輯的示例

    下面小編就為大家分享一篇element-ui 表格實(shí)現(xiàn)單元格可編輯的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • Vue組件data函數(shù)的具體使用

    Vue組件data函數(shù)的具體使用

    在Vue組件中,data函數(shù)用于定義組件的數(shù)據(jù),本文主要介紹了Vue組件data函數(shù)的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • vue-dplayer 視頻播放器實(shí)例代碼

    vue-dplayer 視頻播放器實(shí)例代碼

    今天小編就為大家分享一篇vue-dplayer 視頻播放器實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11

最新評(píng)論

女性| 栾城县| 光山县| 新绛县| 社旗县| 乐亭县| 甘谷县| 交口县| 丰镇市| 阿尔山市| 进贤县| 永平县| 凤冈县| 竹北市| 宜兰市| 安化县| 江油市| 开封市| 铜鼓县| 佛坪县| 白玉县| 平遥县| 襄樊市| 万载县| 丹棱县| 临朐县| 藁城市| 莱州市| 饶阳县| 台东县| 珠海市| 汪清县| 福海县| 宜都市| 分宜县| 恩平市| 天水市| 托克托县| 东兰县| 汾西县| 东方市|