TS + React + Antd + Koa2 + MongoDB 打造 TodoList 全棧應用

前言

JS 做爲一門弱類型語言,時常受到 Java,C# 等老牌編程語言的「歧視」,而且誕生之初,只能運行在瀏覽器端上,被戲稱爲「玩具語言」。早前 Node.JS 的出現,讓 JS 向後端領域進軍。現在 TypeScript 的出現則讓它煥發了新的生命,從本質上向這個語言添加了可選的靜態類型和基於類的面向對象編程,做爲JavaScript的一個超集,與當下最流行的前端框架 React 有着天生的契合度。目前可謂大紅大紫。html

2019年,咱們有必要全面掌握 TypeScript,並應用到實踐中。前端

本項目以功能清晰的 TodoList 爲切入點,結合 React全家桶、Antd 打造代碼健壯性強,用戶界面簡潔的前端應用,以 Koa2 + MongoDB 爲核心構建可維護性高的後端服務。ios

是一個全棧應用 TodoList 的最佳實踐。你們能夠本身動手試一試。git

項目預覽

話很少上,咱們先看實際效果。 線上訪問地址,你們能夠自行註冊體驗。(本身搭建的阿里雲服務器,已設置 HTTPS 安全,不過因爲是學生版,首屏加載速度較慢,請耐心等待,後續會進行優化) github

技術棧

  • 前端
    • TypeScript(使 JS 成爲強類型語言)
    • React(當下最流行的前端框架)
    • Axios(處理 HTTP 請求)
    • Ant-Design(UI 框架)
    • React-Router(處理頁面路由)
    • Redux(數據狀態管理)
    • Redux-Saga(處理異步 Action)
  • 後端
    • Koa2(基於 Node.js 平臺的下一代 web 開發框架)
    • MongoDB(非關係型數據庫)

功能點

  • RESTful 風格接口設計
  • HTTP請求封裝,錯誤處理
  • 組件化,代碼分層
  • 用戶登陸註冊
  • Todo 的關鍵詞查詢
  • Todo 內容修改
  • Todo 狀態更改
  • Todo 記錄刪除

實踐分析

TypeScript

TS最基礎的賦予咱們給JS變量設置類型的能力,還帶來了接口,泛型,枚舉,類,裝飾器,命名空間等全新內容。web

let a: number = 1; // int a = 1;
let b: string = 'Hello'; // string b = 'Hello'
let arr: number[] = [1, 2, 3]; // int arr[] = {1,2,3};
複製代碼

TS能夠約束咱們的傳參,變量類型,接口類型,從而避免在開發時產生沒必要要的錯誤。小夥伴能夠觀看 官方文檔

/interface/UserState.ts爲例,導出了一個接口數據庫

export interface UserState {
    user_id?: string; // ?表明可選
    username?: string;
    err_msg?: string;
}
複製代碼

user繼承UserState接口,因此 會有屬性推導,而在JS中,咱們須要本身輸入user.err_msg,繁瑣且易出錯。 編程

在React,咱們主要經過無狀態組件 function,和有狀態組件 class來構建應用,包括 props的傳遞,函數的傳參,類的繼承等都很是須要類型約定,能夠說TS和React「天生一對」,使用他們,咱們的代碼健壯性提升了一個檔次。

redux狀態管理

狀態管理是目前構建單頁應用中不可或缺的一環,簡單應用使用組件內 State 方便快捷,但隨着應用複雜度上升,會發現數據散落在不一樣的組件,組件通訊會變得異常複雜,這時候就須要redux來管理全局狀態。它遵循三個原則:redux

  • 組件數據來源於 Store,單向流動
  • 只能經過觸發 action 來改變 State,經過定義actionTypes,作到全局唯一
  • Reducer 是純函數

因爲Reducer只能是純函數(簡單來講,一個函數的返回結果只依賴於它的參數,而且在執行過程裏面沒有反作用,咱們就把這個函數叫作純函數。),而當處於請求(Fetch)場景時,Action須要發起異步請求,包含了反作用,因此使用藉助Redux-Saga來處理異步Action,處理後返回成功的同步Action並觸發,此時是一個純函數,最終改變store數據。小程序

以FETCH_TODO(獲取Todo資源)爲例,數據流向以下圖所示:

接口設計

因爲採用的是先後端分離開發,咱們經過約定接口來進行數據交換,而當下最流行的即是 RESTful 風格接口,它有如下幾個要點:

  • 根據請求目的,設置對應 HTTP Method,如 GET 對應讀取資源(Read),PUT 對應更新資源(Update),POST 對應建立資源(Created),DELETE 表明刪除資源(Delete),對應數據庫 CRUD 操做
  • 動詞表示請求方式,名詞表示數據源,通常採用複數形式 如 GET/users/2 獲取 id 爲2的用戶
  • 返回相應的HTTP狀態碼,常見的有200 OK請求成功,201 CREATED建立成功,202 ACCEPTED更新成功,204 NO CONTENT刪除成功,401 UNAUTHORIZED未受權,403 FORBIDDEN禁止訪問,404 NOT FOUND資源不存在,500 INTERNAL SERVER ERROR服務器端內部錯誤

以Todo的路由爲例,咱們能夠設計出如下接口

代碼分層

首先看後端文件目錄:

咱們關注於 db service routes這三個文件夾。

  • db創建數據模型(Model),至關於MySQL的建表環節
  • service調用數據模型處理數據庫的業務邏輯,對數據庫進行CURD,返回加工後的數據
  • routes調用service中的方法處理路由請求,設置請求響應

學過Java的小夥伴都知道,一個接口要經過 Domain層,DAO層,Service層,纔會進入 Controller層調用,咱們的項目相似於這種思想,更好的邏輯分層不只能提升項目的維護性,還能下降耦合度,這在大型項目中尤其重要。

錯誤處理

service/user爲例,咱們定義了userService類,用於處理user的業務邏輯,其中的addUser爲註冊用戶時調用的方法。

因爲咱們設置了usr字段惟一,因此當用戶註冊時,輸入已經註冊過的用戶名,就會拋出異常。這時候,咱們要 catch,並向調用此方法的路由拋出咱們自定義的異常 'save failed'隨後路由層會捕獲錯誤,返回用戶名已存在的HTTP響應。這就是一個較爲典型的的錯誤處理過程。

統一響應

關於API調用的返回結果,爲了格式化響應體,咱們在/utils/response.js編寫處理響應的通用函數。

返回一組消息,指明調用是否成功。這類消息一般具備共同的消息體樣式。 通用返回格式是由msgerror_codedatarequest四個參數組成的JSON響應體:

當咱們請求 GET https://b2d1.top:5000/api/todos/5c6a5b2f6622ab4bf6fed958/all時,獲取指定用戶的全部Todo,返回如下響應體
這不只僅增強了規範性,並且利於前端接收請求,作出更好的判斷或排錯

寫在結尾

本項目還有許多技術要點、開發技巧,因爲篇幅有限,做者就不一一說起了,想繼續深刻了解的小夥伴,請在評論區留言,我會考慮再寫第二篇繼續剖析。

但願小夥伴們參照源碼,親自動手作一個屬於本身的TodoList,共勉!

以後一段時間,可能會推出如何搭建本身的服務器,並設置HTTPS安全教程,還有小程序的全棧開發流程,請期待吧!

TodoList:GitHub地址

相關文章
相關標籤/搜索