摘要:遷移至指南為什么要遷移至本身是動(dòng)態(tài)弱類型的語(yǔ)言,這樣的特點(diǎn)導(dǎo)致了代碼中充斥著很多的報(bào)錯(cuò),給開(kāi)發(fā)調(diào)試和線上代碼穩(wěn)定都帶來(lái)了不小的負(fù)面影響。可行性因?yàn)槭堑某粫?huì)阻止的運(yùn)行,即使存在類型錯(cuò)誤也不例外,這能讓你的逐步遷移至。
Vue2.5+遷移至Typescript指南 為什么要遷移至Typescript
Javascript本身是動(dòng)態(tà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)類型檢查,使很多類型錯(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)門ypeScript是JavaScript的超集,TypeScript 不會(huì)阻止 JavaScript 的運(yùn)行,即使存在類型錯(cuò)誤也不例外,這能讓你的 JavaScript 逐步遷移至 TypeScript。所以可以慢慢地做遷移,一次遷移一個(gè)模塊,選擇一個(gè)模塊,重命名.js文件到.ts,在代碼中添加類型注釋。當(dāng)你完成這個(gè)模塊時(shí),選擇下一個(gè)模塊。
如何將已有的Vue項(xiàng)目遷移至Typescript 安裝依賴Vue官方提供了一個(gè)庫(kù)Vue-class-component,用于讓我們使用Ts的類聲明方式來(lái)編寫(xiě)vue組件代碼。Vue-property-decorator則是在Vue-class-component的基礎(chǔ)上提供了裝飾器的方式來(lái)編寫(xiě)代碼。首先我們需要在package.json中引入這兩個(gè)依賴。
我的項(xiàng)目是基于vue-cli@3.X創(chuàng)建的,還需要在項(xiàng)目中引入@vue/cli-plugin-typescript typescript兩個(gè)依賴來(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引入了太多的依賴,我們應(yīng)該首先從依賴著手,自下而上的遷移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層的代碼提供類型聲明。
聲明文件編寫(xiě)方法一個(gè)js文件如下
//service.js import axios from "@/libs/api.request" export default { /** * 創(chuàng)建賬戶 * @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ù)類型及名稱,但jsdoc畢竟只是注釋,并不能提供類型校驗(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ě)完成了,我們往往在main.js中將service.js導(dǎo)出的實(shí)例綁定在了Vue原型上,使得我們可以在vue組件中通過(guò)vm.$service方便訪問(wèn)service實(shí)例。但是Typescript并不知道Vue實(shí)例上有什么屬性,這時(shí)需要我們?cè)谥疤砑拥?b>shims-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ě)的方式。
至此一個(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)有在類型系統(tǒng)中聲明這些值,按道理應(yīng)該報(bào)Property "$refs" does not exist on type [your_component_name]
真相是$refs vue-router vuex都已經(jīng)給我們聲明了相應(yīng)的類型,我們可以cd ./node_modules/vue/types/目錄中去查看
截取少量代碼如下所示:
export interface Vue { readonly $el: Element; readonly $options: ComponentOptions; 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 ; readonly $props: Record ; readonly $ssrContext: any; readonly $vnode: VNode; readonly $attrs: Record ; readonly $listeners: Record ; }
只要正常的在依賴中安裝了vue-router vuex就已經(jīng)通過(guò)模塊補(bǔ)充的方式將類型添加到了vue實(shí)例上。
在一些項(xiàng)目中,vue-router vuex這些依賴不是通過(guò)安裝在依賴中引入的,而是通過(guò)index.html引入的cdn資源文件,這樣在開(kāi)發(fā)過(guò)程中我們就無(wú)法獲取其類型。
這個(gè)時(shí)候我們可以通過(guò)安裝@types依賴的方式將類型系統(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目錄,引入需要的類型聲明文件。
這樣就可以直接在vue實(shí)例上訪問(wèn)到$store $router等屬性了。
同理當(dāng)你想要引入其他的組件庫(kù)上的一些類型文件時(shí),也是這樣的方式。
在vue開(kāi)發(fā)過(guò)程中我們會(huì)使用this.$refs去訪問(wèn)某一個(gè)具體實(shí)例的方法,但是這在ts中是訪問(wèn)不到的
常見(jiàn)的,比如要想要使用form組件中的validate方法,我們需要給其加上類型斷言
this.$refs.form.validate()變?yōu)?b>(this.$refs.form as Vue & {validate:Function}).validate()
來(lái)告訴編譯器this.$refs.form上有validate方法。
因?yàn)轭愋蛿嘌郧疤釛l件是是當(dāng) S 類型是 T 類型的子集,或者 T 類型是 S 類型的子集時(shí),S 能被成功斷言成 T,所以需要在類型斷言時(shí)合并Vue類型。
同時(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 可以聲明基本類型別名,聯(lián)合類型,元組等類型
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è)?b>tsconfig將其設(shè)置為false就好了。
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 //這樣不允許
未完待續(xù),歡迎補(bǔ)充
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/106242.html
摘要:遷移至指南為什么要遷移至本身是動(dòng)態(tài)弱類型的語(yǔ)言,這樣的特點(diǎn)導(dǎo)致了代碼中充斥著很多的報(bào)錯(cuò),給開(kāi)發(fā)調(diào)試和線上代碼穩(wěn)定都帶來(lái)了不小的負(fù)面影響。可行性因?yàn)槭堑某粫?huì)阻止的運(yùn)行,即使存在類型錯(cuò)誤也不例外,這能讓你的逐步遷移至。 Vue2.5+遷移至Typescript指南 為什么要遷移至Typescript Javascript本身是動(dòng)態(tài)弱類型的語(yǔ)言,這樣的特點(diǎn)導(dǎo)致了Javascript代碼...
摘要:引入全面指南系列目錄引入全面指南引入全面指南篇寫(xiě)在前面寫(xiě)這篇文章時(shí)的我,使用經(jīng)驗(yàn)三個(gè)多月,完全空白,花了大概三個(gè)晚上把手頭項(xiàng)目遷移至,因此這篇文章更像個(gè)入門指引。見(jiàn)文章引入全面指南篇完整代碼見(jiàn)庫(kù),分支為整合示例,分支為不含的基礎(chǔ)示例。 Vue2.5+ Typescript 引入全面指南 系列目錄: Vue2.5+ Typescript 引入全面指南 Vue2.5+ Typescrip...
摘要:哪吒別人的看法都是狗屁,你是誰(shuí)只有你自己說(shuō)了才算,這是爹教我的道理。哪吒去他個(gè)鳥(niǎo)命我命由我,不由天是魔是仙,我自己決定哪吒白白搭上一條人命,你傻不傻敖丙不傻誰(shuí)和你做朋友太乙真人人是否能夠改變命運(yùn),我不曉得。我只曉得,不認(rèn)命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出處 查看github最新的Vue...
摘要:引入全面指南篇系列目錄引入全面指南引入全面指南篇前言正是我下決心引入的核心痛點(diǎn)。其中,可以通過(guò)建立輔助函數(shù)形式,簡(jiǎn)單繞開(kāi)。只是類型均為建議不使用,以明確指定類型及調(diào)用可通過(guò)上述下輔助函數(shù),手動(dòng)開(kāi)啟類型推導(dǎo)及類型推導(dǎo),暫時(shí)只能手動(dòng)指定。 Vue2.5+ Typescript 引入全面指南 - Vuex篇 系列目錄: Vue2.5+ Typescript 引入全面指南 Vue2.5+ T...
閱讀 924·2021-09-29 09:35
閱讀 1266·2021-09-28 09:36
閱讀 1538·2021-09-24 10:38
閱讀 1087·2021-09-10 11:18
閱讀 647·2019-08-30 15:54
閱讀 2513·2019-08-30 13:22
閱讀 1977·2019-08-30 11:14
閱讀 712·2019-08-29 12:35