写在最前面
- 这篇文章适用者,node 初学者的前端同学,或者对 react 有兴趣的后端同学。文章难度为入门,即使不太了解这些语言的同学稍微查阅资料也能看懂。
- 提示:需要对 Typescript 有一定了解,server 和 client 端均使用 Typescript
- 默认已经安装好
yarn
或者npm
技术栈参考
- 如果对上面技术栈不太熟悉的同学可以优先参考以下文档
NodeJS App(server 端)
1、初始化
- 新建文件夹
mkdir server cd server
- 初始化
yarn init
- 构建文件目录
├── dist ├── node_modules ├── src ├── app.ts ├── controllers | └── todos | └── index.ts ├── models | └── todo.ts ├── routes | └── index.ts └── types └── todo.ts ├── nodemon.json ├── package.json ├── tsconfig.json
app.ts 就是我们项目的入口,dist 文件夹主要是负责 ts 编译输出文件,
nodemon.json
是数据库的配置项,后面会提到。
2、配置
- 我们来配置
ts.config
{ "compilerOptions": { "target": "es6", "module": "commonjs", "outDir": "dist/js", "rootDir": "src", "strict": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true }, "include": ["src/**/*"], "exclude": ["src/types/*.ts", "node_modules", ".vscode"] }
outDir: 告诉编译器,把编译好的 js 文件输出到 dist/js 目录
rootDir: ts 需要编译的根目录
include: 告诉编译器具体需要编译的地址.
exclude: 排除不需要编译的文章
- 安装
typescript
yarn add typescript -g
- 安装
express
和MongoDB
依赖和他们的 @types
yarn add express cors mongoose yarn add -D @types/node @types/express @types/mongoose @types/cors
- 安装用来编译 Typescript 的
concurrently
和nodemon
yarn add -D concurrently nodemon
- 最后我们添加 build 和 start 脚本
"scripts": { "build": "tsc", "start": "concurrently \"tsc -w\" \"nodemon dist/js/app.js\"" }
ps:这里
tsc
需要全局安装 ts 才能进行
concurrently
最主要的工作就是帮助我们编译 Typescript,进行热更新。
3、code
3.1 创建 todolist @types
- types/todo.ts
import { Document } from "mongoose" export interface ITodo extends Document { name: string description: string status: boolean }
创建的新的 @types 是来自 mongoose 的 Document,也就是基础的文本格式。
3.2 创建 todolist Model
- models/todo.ts
import { ITodo } from "./../types/todo" import { model, Schema } from "mongoose" const todoSchema: Schema = new Schema( { name: { type: String, required: true, }, description: { type: String, required: true, }, status: { type: Boolean, required: true, }, }, { timestamps: true } ) export default model<ITodo>("Todo", todoSchema)
创建一个类型库定义 dotolist 的数据类型。
3.3 API controllers
现在我们在 controller 中添加几个 todolist 相关的方法。
getTodos
- controllers/todos/index.ts
import { Response, Request } from "express" import { ITodo } from "./../../types/todo" import Todo from "../../models/todo" const getTodos = async (req: Request, res: Response): Promise<void> => { try { const todos: ITodo[] = await Todo.find() res.status(200).json({ todos }) } catch (error) { throw error } }
需要引入 express 来明确的定义我们的 response 和 request 类型。具体的解析如上,我们使用 json 来定义我们的数据。这个函数来初始化我们的 todolist 的数据,页面加载会调用。
addTodo
- controllers/todos/index.ts
const addTodo = async (req: Request, res: Response): Promise<void> => { try { const body = req.body as Pick<ITodo, "name" | "description" | "status"> const todo: ITodo = new Todo({ name: body.name, description: body.description, status: body.status, }) const newTodo: ITodo = await todo.save() const allTodos: ITodo[] = await Todo.find() res .status(201) .json({ message: "Todo added", todo: newTodo, todos: allTodos }) } catch (error) { throw error } }
addTodo 函数用于添加新增一条的 list 和更新总的 lists。
updateTodo
- controllers/todos/index.ts
const updateTodo = async (req: Request, res: Response): Promise<void> => { try { const { params: { id }, body, } = req const updateTodo: ITodo | null = await Todo.findByIdAndUpdate( { _id: id }, body ) const allTodos: ITodo[] = await Todo.find() res.status(200).json({ message: "Todo updated", todo: updateTodo, todos: allTodos, }) } catch (error) { throw error } }
更新一条 list,变成完成状态。我们需要传相关的 id 确定具体的 list。
4、API routes
- routes/index.ts
import { Router } from "express" import { getTodos, addTodo, updateTodo, deleteTodo } from "../controllers/todos" const router: Router = Router() router.get("/todos", getTodos) router.post("/add-todo", addTodo) router.put("/edit-todo/:id", updateTodo) router.delete("/delete-todo/:id", deleteTodo) export default router
好了现在基本的方法对应的路由就构建好了
5、MongoDB 数据库配置
- nodemon.json
{ "env": { "MONGO_USER": "your-username", "MONGO_PASSWORD": "your-password", "MONGO_DB": "your-db-name" } }
具体怎么配置?可以看我的这篇 mongoDB clound 云数据库的配置文章。
- app.ts
import express, { Express } from 'express'; import mongoose from 'mongoose'; import cors from 'cors'; import todoRoutes from './routes'; import bodyParser from 'body-parser'; const app: Express = express(); // 这里默认 4000 端口,后续 client 端会用到,如果想自定义,保持一致即可 const PORT: string | number = 4000; // const PORT: string | number = process.env.PORT || 4000; console.log(process.env.PORT); app.use(cors()); // 跨域处理 app.use(bodyParser.json()); // post 请求处理 app.use(bodyParser.urlencoded({ extended: false })); app.use(todoRoutes); // 咋们的 api 路由处理 const uri: string = `mongodb+srv://${process.env.MONGO_USER}:${process.env.MONGO_PASSWORD}@cluster0.4qpw4.mongodb.net/${process.env.MONGO_DB}?retryWrites=true&w=majority`; const options = { useNewUrlParser: true, useUnifiedTopology: true }; mongoose.set('useFindAndModify', false); mongoose .connect(uri, options) .then(() => app.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`) ) ) .catch((error) => { throw error; });
5、总结
- ok,现在我们的 server 端和 clound database就完成了,下篇来介绍 client 端的构建。
- 需要 gitignore的可以查看下面的 source code
6、源码
- github.com/lpove/todol…
- 大家可以按照 branch 分支的顺序查看