項目中使用TypeScript的TodoList實例詳解
為什麼用todolist
現代的框架教程目前再也不是寫個hello world那麼簡單瞭,而是需要有一定基礎能力能夠做到數據綁定、遍歷、條件判斷等各種邏輯,而能完成這一系列內容的,todolist就是個很好的實現,比如react的教程、solijs教程都是以todolist為例
當然,你如果想看各種框架實現todolist的話,你可以訪問TodoMVC 這裡面展示瞭各種框…
todolist的ts化
但是對於ts教程來說,隻有官方的一些實例,並沒有一個很好的項目上的教程,也就是有關實戰的部分,很多同學在學習瞭ts之後,隻會一些基礎的js類型的設置,放在項目中就不清楚瞭,所以我們就出瞭這個教程
當然在開始之前,我們要瞭解這個教程不依賴任何的前端庫,比如react,vue等,同時也為瞭節省時間,我們僅僅是放出一些關鍵的ts代碼,不需要將整個應用都展示出來,同樣能夠讓你知道ts的使用
數據到視圖
一個tudolist對應的數據是怎麼樣的?就拿剛才的視圖來看的話,它應該是一個對象數組,數據應該是這樣的
[ { id: 1, text: '待辦事項1', done: false }, { id: 2, text: '待辦事項2', done: false }, { id: 3, text: '待辦事項3', done: false } ]
其中id是每一個代辦事項的唯一標識,text是事項名稱,done表示是否完成
當我們點擊完成的時候,實際上就是每一項的done發生瞭變化,數據發生變化之後驅動我們的視圖做出對應的改變
實現handleTodoItem
對應的上述的點擊事件,我們實現一下它的偽代碼,當其點擊的時候,需要處理對應的數據,先使用js實現
function handleTodoItem(todo){ // 點擊的時候todo中的done的佈爾值取反 return { ...todo, done: !todo.done } }
然後我們使用ts進行優化
type Todo = { id: number; text: string; done: boolean; } // 如果某個變量是todo類型,可以這樣 const todoItem: Todo = { id: 1, text: '待辦事項1', done: false }
這樣ts類型就是正常的,如果相應的todoItem不匹配,則編譯就會發生錯誤,可以讓錯誤提前感知,並且如果項目中有配置的ts相關,vscode中就會給出對應的錯誤信息
對應到handleTodoItem這個方法中,應該怎麼寫呢?
function handleTodoItem(todo: Todo): Todo { // 邏輯實現 }
readonly
對於handleTodoItem這個函數來說,函數應該是無副作用的,所以傳進去的todo對象,不應該發生變化,而是返回一個新的對象
比如這種方法,雖然能夠實現同樣的內容,但是它是有副作用的,改變瞭傳入的參數,是不可取的
function handleTodoItem(todo: Todo):Todo { // 點擊的時候todo中的done的佈爾值取反 todo.done = !todo.done return todo }
但是這種的ts並不會報錯,怎麼辦?那就需要借助我們的ts進行類型校驗,你可以這樣
type Todo = { readonly id: number; readonly text: string; readonly done: boolean; }
當你嘗試修改修改的話,就會發生ts錯誤,不允許修改,因為Todo類型是隻讀的,當然你也可以這樣設置對象中所有的屬性為隻讀
type Todo = Readonly<{ id: number; text: string; done: boolean; }>
在ts中,這種Readonly的關鍵詞還有很多,比如Required,Partial等,如有需要,大傢可自行搜索
分類
對於已經完成的list,我們需要將其進行分類篩選,比如我們要篩選出所有已經完成的項目,那麼表現就是一個數組,並且done為true
[ { id: 1, text: '待辦事項1', done: true }, { id: 2, text: '待辦事項2', done: true } ]
如何表示一個數組類內容呢?Todo[]
這種方式就能表示上述數據,同樣的,函數的參數是不允許修改的,避免副作用,所以可以這樣
function completeTodoList( todos: readonly Todo[] ): Todo[] { // ... }
當然,由於Todo的type中的done為boolean,但是在completeTodoList中done的值為true,所以我們需要重新定義一個類型
type CompletedTodo = Readonly<{ id: number; text: string; done: true; }>
所以上述的方法就會變成
function completeTodoList( todos: readonly Todo[] ): CompletedTodo[] { // ... }
交叉類型
對於上面的Todo和CompletedTodo類型,其中這兩個類型的id和text都是重復的,我們可以刪除重復的邏輯,使用交叉類型
舉個例子
type A = {a: number} type B = {b: string} type AandB = A & B // 結果為 // { // a: number // b: string // }
當兩個類型key相同時,第二個key會覆蓋掉第一個的內容
type A = {key: number} type B = {key: string} type AandB = A & B // 結果為 // { // key: string // }
那針對Todo和CompletedTodo類型,我們想從Todo通過交叉類型得到CompletedTodo,該怎麼做呢?
type CompletedTodo = Todo & { readonly done: true }
是不是很簡潔,並且去除瞭一些重復代碼
新增功能
如果在Todo的基礎上,我們新增瞭一個功能,對應的todo的優先級,使用priority這個字段表示
並且一共有三種優先級
!!!
!!
!
你可以priority: 2
這樣設置,展示為【!!】當然你也可以自定義,比如
{ priority: { custom: '緊急' } }
則展示為【緊急】,所以這時候數據變成瞭
[ { id: 1, text: '待辦事項1', done: false, priority: 1 }, { id: 2, text: '待辦事項2', done: false, priority: 2 }, { id: 3, text: '待辦事項3', done: false, priority: { custom: '緊急' } }, { id: 4, text: '待辦事項4', done: false }, ]
我們已經有瞭Todo類型,如何新增一個key呢?
聯合類型
上面我們之後交叉類型通過 &
連接,那聯合類型則是通過 |
連接,同樣的舉個例子
type Foo = number | string;
這表示Foo類型可以是一個數字,也可以是一個string類型,所以我們的priority類型可以這樣設置
type Priority = 1 | 2 | 3 | { custom: string };
這個時候priority就是我們想要的內容瞭,所以todo的類型可以變一下
type Todo = Readonly<{ id: number; text: string; done: boolean; priority: Priority; }>
可選屬性
上面的priority這個屬性目前是必填的,但是這個屬性我們可以不寫,也就是todo可以沒有優先級,針對這種情況,我們可以使用可選屬性
type Todo = Readonly<{ id: number; text: string; done: boolean; priority?: Priority; }>
在對應的地方添加一個?即可
數據轉視圖
那對應的priority的數據有瞭,如何把1,2,3這種的轉成!!!的形式呢?
可以自定義一個函數,也就是priorityToString
priorityToString(1) // ! priorityToString(2) // !! priorityToString(3) // !!! priorityToString({ custom: '緊急' }) // 緊急
情況比較少,可能你會這樣寫
function priorityToString(priority: Priority): string { if(priority === 1){ return '!' }else if(priority === 2){ return '!!' }else if(priority === 3){ return '!!!' }else{ return priority.custom } }
聯合類型我們通過if條件進行判斷的時候,它會自動確認每個if條件下的參數類型,這也是聯合類型的強大之處
總結
基本上我們項目中用到的一些知識點這裡都概括瞭,通過一個簡單的項目,將ts的一些基本類型給大傢做瞭一個簡要的說明
參考:ts.chibicode.com/todo/
以上就是項目中使用TypeScript的TodoList實例詳解的詳細內容,更多關於TypeScript TodoList使用的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- .NET 6開發TodoList應用之實現查詢排序
- vue如何自定義事件傳參
- .NET 6開發TodoList應用之使用MediatR實現POST請求
- 淺談typescript中keyof與typeof操作符用法
- .NET 6開發TodoList應用之使用AutoMapper實現GET請求