typescript vuex_Vue3+TypeScript完整項目上手教程

作者:TinssonTai

https://juejin.im/post/6875713523968802829

一個完整的Vue3+Ts項目,支持.vue和.tsx寫法

項目地址:https://github.com/vincentzyc/vue3-demo.git

TypeScript 是JS的一個超集,主要提供了類型系統和對ES6的支持,使用 TypeScript 可以增加代碼的可讀性和可維護性,在 reactvue 社區中也越來越多人開始使用TypeScript。從最近發布的 Vue3 正式版本來看, Vue3 的源碼就是用 TypeScript 編寫的,更好的 TypeScript 支持也是這一次升級的亮點。當然,在實際開發中如何正確擁抱 TypeScript 也是遷移至 Vue3 的一個小痛點,這里就針對 Vue3TypeScript 展開一些交流。

ac097ebfea0415a79e66faf731a12cfc.png

96.8%的代碼都是TypeScript,支持的力度也是相當大?

  • Vue3入口: https://github.com/vuejs/vue-next

項目搭建

在官方倉庫的 Quickstart 中推薦用兩種方式方式來構建我們的 SPA 項目:

  • vite
npm?init?vite-app?sail-vue3?#?OR?yarn?create?vite-app?sail-vue3
  • vue-cli
npm?install?-g?@vue/cli?#?OR?yarn?global?add?@vue/cli
vue?create?sail-vue3
#?select?vue?3?preset

vite 是一個由原生ESM驅動的Web開發構建工具,打開 vite 依賴的 package.json 可以發現在 devDependencies 開發依賴里面已經引入了TypeScript ,甚至還有 vuex , vue-router , less , sass 這些本地開發經常需要用到的工具。vite 輕量,開箱即用的特點,滿足了大部分開發場景的需求,作為快速啟動本地 Vue 項目來說,這是一個非常完美的工具。

后面的演示代碼也是用vite搭的

vue2.x 走過來的掘友肯定知道 vue-cli 這個官方腳手架, vue3 的更新怎么能少得了 vue-cli 呢, vue-cli 更強調的是用 cli 的方式進行交互式的配置,選擇起來更加靈活可控。豐富的官方插件適配,GUI的創建管理界面,標準化開發流程,這些都是 vue-cli 的特點。

  • vue-cli ? TypeScript STEP1
15916dca614627d39994c2384c07b5c4.png
  • vue-cli ? TypeScript STEP2
89cd0977e9ed5380d9f9920a260aeb1d.png

想要預裝TypeScript,就需要選擇手動配置,并check好TypeScript

忘記使用選擇 TypeScript 也沒事,加一行cli命令就行了

vue?add?typescript

最后,別忘了在 .vue 代碼中,給 script 標簽加上 lang="ts"

<script?lang="ts">

Option API風格

Vue2.x 使用過 TypeScript 的掘友肯定知道引入 TypeScript 不是一件簡單的事情:

  1. 要用 vue-class-component 強化 vue 組件,讓 Script 支持 TypeScript 裝飾器
  2. vue-property-decorator 來增加更多結合 Vue 特性的裝飾器
  3. 引入 ts-loaderwebpack 識別 .ts .tsx 文件
  4. .....

然后出來的代碼風格是這樣的:

@Component({
????components:{?componentA,?componentB},
})
export?default?class?Parent?extends?Vue{
??@Prop(Number)?readonly?propA!:?number?|?undefined
??@Prop({?default:?'default?value'?})?readonly?propB!:?string
??@Prop([String,?Boolean])?readonly?propC!:?string?|?boolean?|?undefined

??//?data信息
??message?=?'Vue2?code?style'

??//?計算屬性
??private?get?reversedMessage?():?string[]?{
??????return?this.message.split('?').reverse().join('')
??}

??//?method
??public?changeMessage?():?void?{
????this.message?=?'Good?bye'
??}
}

class 風格的組件,各種裝飾器穿插在代碼中,有點感覺自己不是在寫 vue ,些許凌亂?,所以這種曲線救國的方案在 vue3 里面肯定是行不通的。

vue3 中可以直接這么寫:

import?{?defineComponent,?PropType?}?from?'vue'

interface?Student?{
??name:?string
??class:?stringage:?number
}const?Component?=?defineComponent({
??props:?{
????success:?{?type:?String?},
????callback:?{
??????type:?Function?as?PropType<()?=>?void>
????},
????student:?{
??????type:?Object?as?PropType,required:?true
????}
??},
??data()?{return?{message:?'Vue3?code?style'
????}
??},computed:?{
????reversedMessage():?string?{return?this.message.split('?').reverse().join('')
????}
??}
})

vueprops 進行復雜類型驗證的時候,就直接用 PropType 進行強制轉換, data 中返回的數據也能在不顯式定義類型的時候推斷出大多類型, computed 也只用返回類型的計算屬性即可,代碼清晰,邏輯簡單,同時也保證了 vue 結構的完整性。

Composition API風格

vue3Composition API 代碼風格中,比較有代表性的api就是 refreactive ,我們看看這兩個是如何做類型聲明的:

ref

import?{?defineComponent,?ref?}?from?'vue'

const?Component?=?defineComponent({
setup()?{
??const?year?=?ref(2020)
??const?month?=?ref('9')
??month.value?=?9?//?OKconst?result?=?year.value.split('')?//?=>?Property?'split'?does?not?exist?on?type?'number'
?}
})

分析上面的代碼,可以發現如果我們不給定 ref 定義的類型的話, vue3 也能根據初始值來進行類型推導,然后需要指定復雜類型的時候簡單傳遞一個泛型即可。

Tips:如果只有setup方法的話,可以直接在defineComponent中傳入setup函數

const?Component?=?defineComponent(()?=>?{
????const?year?=?ref(2020)
????const?month?=?ref('9')
????month.value?=?9?//?OKconst?result?=?year.value.split('')?//?=>?Property?'split'?does?not?exist?on?type?'number'
})

reactive

import?{?defineComponent,?reactive?}?from?'vue'

interface?Student?{
??name:?string
??class?:?stringage:?number
}export?default?defineComponent({
??name:?'HelloWorld',
??setup()?{
????const?student?=?reactive({?name:?'阿勇',?age:?16?})//?orconst?student:?Student?=?reactive({?name:?'阿勇',?age:?16?})//?orconst?student?=?reactive({?name:?'阿勇',?age:?16,?class:?'cs'?})?as?Student
??}
})

聲明 reactive 的時候就很推薦使用接口了,然后怎么使用類型斷言就有很多種選擇了,這是 TypeScript 的語法糖,本質上都是一樣的。

自定義Hooks

vue3 借鑒 react hooks 開發出了 Composition API ,那么也就意味著 Composition API 也能進行自定義封裝 hooks ,接下來我們就用 TypeScript 風格封裝一個計數器邏輯的 hooks ( useCount ):

首先來看看這個 hooks 怎么使用:

import?{?ref?}?from?'/@modules/vue'
import??useCount?from?'./useCount'

export?default?{
??name:?'CountDemo',
??props:?{
????msg:?String
??},
??setup()?{
????const?{?current:?count,?inc,?dec,?set,?reset?}?=?useCount(2,?{
??????min:?1,
??????max:?15
????})
????const?msg?=?ref('Demo?useCount')

????return?{
??????count,
??????inc,
??????dec,
??????set,
??????reset,
??????msg
????}
??}
}

出來的效果就是:

a2732fa512a9411c25d8faa58f6324ed.gif

貼上 useCount 的源碼:

import?{?ref,?Ref,?watch?}?from?'vue'

interface?Range?{
??min?:?number,
??max?:?number
}

interface?Result?{
??current:?Ref,inc:?(delta?:?number)?=>?void,dec:?(delta?:?number)?=>?void,set:?(value:?number)?=>?void,reset:?()?=>?void
}export?default?function?useCount(initialVal:?number,?range?:?Range):?Result?{const?current?=?ref(initialVal)const?inc?=?(delta?:?number):?void?=>?{if?(typeof?delta?===?'number')?{
??????current.value?+=?delta
????}?else?{
??????current.value?+=?1
????}
??}const?dec?=?(delta?:?number):?void?=>?{if?(typeof?delta?===?'number')?{
??????current.value?-=?delta
????}?else?{
??????current.value?-=?1
????}
??}const?set?=?(value:?number):?void?=>?{
????current.value?=?value
??}const?reset?=?()?=>?{
????current.value?=?initialVal
??}
??watch(current,?(newVal:?number,?oldVal:?number)?=>?{if?(newVal?===?oldVal)?returnif?(range?&&?range.min?&&?newVal???????current.value?=?range.min
????}?else?if?(range?&&?range.max?&&?newVal?>?range.max)?{
??????current.value?=?range.max
????}
??})return?{
????current,
????inc,
????dec,set,
????reset
??}
}

分析源碼

這里首先是對 hooks 函數的入參類型和返回類型進行了定義,入參的 Range 和返回的 Result 分別用一個接口來指定,這樣做了以后,最大的好處就是在使用 useCount 函數的時候,ide就會自動提示哪些參數是必填項,各個參數的類型是什么,防止業務邏輯出錯。

a449fda78c57b0e2747ecd724aee518c.png

接下來,在增加 inc 和減少 dec 的兩個函數中增加了 typeo 類型守衛檢查,因為傳入的 delta 類型值在某些特定場景下不是很確定,比如在 template 中調用方法的話,類型檢查可能會失效,傳入的類型就是一個原生的 Event

關于 ref 類型值,這里并沒有特別聲明類型,因為 vue3 會進行自動類型推導,但如果是復雜類型的話可以采用類型斷言的方式:ref(initObj) as Ref

小建議 ?

AnyScript

在初期使用 TypeScript 的時候,很多掘友都很喜歡使用 any 類型,硬生生把TypeScript 寫成了 AnyScript ,雖然使用起來很方便,但是這就失去了 TypeScript 的類型檢查意義了,當然寫類型的習慣是需要慢慢去養成的,不用急于一時。

Vetur

vetur 代碼檢查工具在寫vue代碼的時候會非常有用,就像構建 vue 項目少不了 vue-cli 一樣,vetur 提供了 vscode 的插件支持,趕著升級 vue3 這一波工作,順帶也把 vetur 也帶上吧。

bc270f6877d639bbbbfdc0e3b12e84b7.png

一個完整的Vue3+ts項目

├─public
│??????favicon.ico
│??????index.html
└─src
????│??App.vue
????│??main.ts
????│??shims-vue.d.ts
????├─assets
????│??│??logo.png
????│??└─css
????│??????????base.css
????│??????????main.styl
????├─components
????│??│??HelloWorld.vue
????│??└─base
????│??????????Button.vue
????│??????????index.ts
????│??????????Select.vue
????├─directive
????│??????focus.ts
????│??????index.ts
????│??????pin.ts
????├─router
????│??????index.ts
????├─store
????│??????index.ts
????├─utils
????│??│??cookie.ts
????│??│??deep-clone.ts
????│??│??index.ts
????│??│??storage.ts
????│??└─validate
????│??????????date.ts
????│??????????email.ts
????│??????????mobile.ts
????│??????????number.ts
????│??????????system.ts
????└─views
????????│??About.vue
????????│??Home.vue
????????│??LuckDraw.vue
????????│??TodoList.vue
????????└─address
????????????????AddressEdit.tsx
????????????????AddressList.tsx
  • .vue寫法

??...



???...




  • tsx寫法
import?{?ref,?reactive?}?from?"vue";
import?{?AddressList,?NavBar,?Toast,?Popup?}?from?"vant";
import?AddressEdit?from?'./AddressEdit'
import?router?from?'@/router'

export?default?{
??setup()?{
????const?chosenAddressId?=?ref('1')
????const?showEdit?=?ref(false)

????const?list?=?reactive([
??????{
????????id:?'1',
????????name:?'張三',
????????tel:?'13000000000',
????????address:?'浙江省杭州市西湖區文三路?138?號東方通信大廈?7?樓?501?室',
????????isDefault:?true,
??????},
??????{
????????id:?'2',
????????name:?'李四',
????????tel:?'1310000000',
????????address:?'浙江省杭州市拱墅區莫干山路?50?號',
??????},
????])
????const?disabledList?=?reactive([
??????{
????????id:?'3',
????????name:?'王五',
????????tel:?'1320000000',
????????address:?'浙江省杭州市濱江區江南大道?15?號',
??????},
????])

????const?onAdd?=?()?=>?{
??????showEdit.value?=?true
????}
????const?onEdit?=?(item:?any,?index:?string)?=>?{
??????Toast('編輯地址:'?+?index);
????}

????const?onClickLeft?=?()?=>?{
??????router.back()
????}

????const?onClickRight?=?()?=>?{
??????router.push('/todoList')
????}

????return?()?=>?{
??????return?(
????????
????????????
????????????left-text="返回"
????????????right-text="Todo"
????????????left-arrow
????????????onClick-left={onClickLeft}
????????????onClick-right={onClickRight}
??????????/>????????????vModel={chosenAddressId.value}
????????????list={list}
????????????disabledList={disabledList}
????????????disabledText="以下地址超出配送范圍"
????????????defaultTagText="默認"
????????????onAdd={onAdd}
????????????onEdit={onEdit}
??????????/>

??????);
????};
??}
};

結束

不知不覺, Vue 都到3的One Piece時代了, Vue3 的新特性讓擁抱 TypeScript 的姿勢更加從容優雅, Vue 面向大型項目開發也更加有底氣了,點擊查看更多。

點個『在看』支持下?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/397043.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/397043.shtml
英文地址,請注明出處:http://en.pswp.cn/news/397043.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JS中window.showModalDialog()詳解

window.showModalDialog()方法用來創建一個顯示HTML內容的模態對話框。 window.showModelessDialog()方法用來創建一個顯示HTML內容的非模態對話框。 使用方法&#xff1a; vReturnValue window.showModalDialog(sURL [, vArguments] [,sFeatures]) vReturnValue window.show…

一個簡單的javascript節流器實現

節流器 javascript的節流器主要用于延緩某些動作的執行&#xff0c;比如ajax請求&#xff0c;如果input框注冊了input事件&#xff0c;那么當用戶輸入時就會持續的觸發這個事件&#xff0c;如果回調函數中持續的通過ajax調用后臺的接口&#xff0c;就會對服務器產生一定壓力。這…

一些會用到的知識

為什么80%的碼農都做不了架構師&#xff1f;>>> HtmlAgilityPack 用來解析HTML代碼 microsoft.mshtml CsQuery 解析HTML代碼 轉載于:https://my.oschina.net/uwith/blog/813725

eclipse怎么升級到java ee,如何為Java EE開發人員升級Eclipse?

Is there any non-painful way to upgrade an Eclipse installation? I have tried browsing the eclipse site but I cannot find an useful description.解決方案Add the update URL to your available sites:Window > Preferences > Install/Update > Available S…

LeetCode 7 Reverse Integer(反轉數字)

題目來源&#xff1a;https://leetcode.com/problems/reverse-integer/ Reverse digits of an integer. Example1: x 123, return 321Example2: x -123, return -321 解題思路&#xff1a; 其實這道題看起來非常簡單&#xff0c;要實現也是幾行代碼的事。但是有個小問題容易被…

各種蘊含算法思想的DP - 3

內容中包含 base64string 圖片造成字符過多&#xff0c;拒絕顯示轉載于:https://www.cnblogs.com/cmyg/p/9566723.html

python圖像對比_用python實現對比兩張圖片的不同

from PIL import Image from PIL import ImageChops def compare_images(path_one, path_two, diff_save_location): """ 比較圖片&#xff0c;如果有不同則生成展示不同的圖片 參數一: path_one: 第一張圖片的路徑 參數二: path_two: 第二張圖片的路徑 參數三:…

Kafka 分布式環境搭建

這篇文章將介紹如何搭建kafka環境&#xff0c;我們會從單機版開始&#xff0c;然后逐漸往分布式擴展。單機版的搭建官網上就有&#xff0c;比較容易實現&#xff0c;這里我就簡單介紹下即可&#xff0c;而分布式的搭建官網卻沒有描述&#xff0c;我們最終的目的還是用分布式來解…

Docker Machine搭建并加入節點

對于集群服務器來講&#xff0c;要在每臺機器上手動安裝Docker是一件及其痛苦的事情&#xff0c;還好有Docker Machine這一工具&#xff0c;Docker三劍客中的一角. 一、Docker Machine介紹 這個工具已經出了比較久了&#xff0c;Docker Machine官方介紹&#xff1a;https://doc…

ASPNET5的依賴注入

ASP.NET5設計的時候就是以DI為基礎的&#xff0c;它可以利用內建的框架在Startup類的方法中&#xff0c;把依賴注入進去。應用服務也可以被配置的注入。默認的服務容器提供一些基本的功能&#xff0c;它并不打算代替現代主流的DI框架。 1. 什么是Dependency Injection? DI的概…

java 權限控制 demo_Java-訪問控制權限

Java面向對象-訪問控制權限Java中&#xff0c;可以通過一些Java關鍵字&#xff0c;來設置訪問控制權限&#xff1b;主要有 private(私有)&#xff0c; package(包訪問權限)&#xff0c;protected(子類訪問權限)&#xff0c;public(公共訪問權限)privatepackageprotectedpublic同…

《未來世界的幸存者》筆記

https://ruanyf.github.io/survivor/ 這兩天一直在上下班途中&#xff0c;讀阮一峰的這本書 《未來世界的幸存者》。還是有不少感慨的。做一下記錄。 未來人類社會的形態&#xff0c;將發生顛覆性的變化。舊的社會結構已經在崩潰了&#xff0c;但社會底層的機會變得更少了&…

python類中沒有屬性_如何在python語言中在類中刪除屬性和添加屬性

在python語言中的類&#xff0c;可以使用class定義類&#xff0c;調用__init__方法進行初始化&#xff1b;默認傳入self&#xff0c;可以在后面在添加幾個屬性。可以使用setattr()添加屬性&#xff0c;也可以使用delattr()刪除屬性。下面利用幾個實例說明這兩個方法的用法&…

mysql 數據復制停止工作_linux – Mysql GTID復制停止工作

我在主服務器和從服務器之間設置了mysql gtid復制.有趣的是,我發現復制在幾分鐘后停止工作,我必須使用stop slave并啟動slave來重啟mysql復制.誰能告訴我是什么原因導致這個問題&#xff1f;改變奴隸主&#xff1a;mysql> change master to-> master_host master.com,-&…

python學生管理系統gui版好例子網_python圖書管理系統gui 相關實例(示例源碼)下載 - 好例子網...

開發語言&#xff1a;Python | 大小&#xff1a;19.05M | 發布時間&#xff1a;2019-05-27 | 發布人&#xff1a;李易峰 相關標簽&#xff1a; 立即下載 開發語言&#xff1a;Python | 大小&#xff1a;0.21M | 發布時間&#xff1a;2020-08-23 | 發布人&#xff1a;聶嘉輝 相關…

COM組件的運行機制

COM組件的運行機制  構造一個創建COM組件的最小框架結構    IUnknown *pUnkNULL;    IObject *pObjectNULL;    CoInitialize(NULL);    CoCreateInstance(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IID_IUnknown, (void**)&pUnk);    pUnk->Qu…

申請去國外讀博士

必須要做的事情是&#xff1a; 考過GRE和TOEFL 準備推薦信 個人CV 聯系導師一般就是發郵件 轉載于:https://www.cnblogs.com/zhulinmails/p/5078695.html

動態編譯

下面的demo就涵蓋了動態編譯和運行類的過程 package 動態編譯; import java.lang.reflect.Method;import java.net.URL;import java.net.URLClassLoader; import javax.tools.JavaCompiler;import javax.tools.ToolProvider; public class Demo { public static void main(Stri…

python怎么打開spyder_Python開發環境Spyder安裝方法

Spyder(Scientific PYthon Development EnviRonment)是一個強大的交互式 Python 語言開發環境&#xff0c;提供高級的代碼編輯、交互測試、調試等特性&#xff0c;支持包括 Windows、Linux 和 OS X 系統。 本文在只安裝過python2.7的Win7環境下進行安裝Spyder&#xff0c;其他環…

矩陣、向量求導法則

復雜矩陣問題求導方法&#xff1a;可以從小到大&#xff0c;從scalar到vector再到matrix。 x is a column vector, A is a matrix practice: 轉載于:https://www.cnblogs.com/vincentQin/p/5406010.html