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地址

相关文章
相关标签/搜索