Egg快速入门1:从0开始实现Eggjs的CRUD

1,322 阅读4分钟

这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。

1.Egg.js和Express,Koa.js对比

Express 是 Node.js 社区广泛使用的框架,简单且扩展性强,非常适合做个人项目。

Koa 和 Express 的设计风格非常类似,Koa 是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架

而 Egg 选择了 Koa 作为其基础框架,在它的模型基础上,进一步对它进行了一些增强。总结来说具有以下特点。

2.Egg.js的项目搭建(借助官方egg脚手架)

初始化项目

$ mkdir egg-example && cd egg-example
$ npm init egg --type=simple
$ npm i

启动项目

$ npm run dev
$ open http://localhost:7001

脚手架主要是安装了egg,egg-bin两个重要包,然后手动搭建controller,service层。官方脚手架提供了标准的脚手架目录结构,有兴趣的参考官网搭建。网络卡顿的可以安装nrm切换npm镜像源。后期我会做一期搭建私有npm源

npm i nrm -g
##查看镜像源
nrm ls
##使用指定的镜像源比如yarn
nrm use yarn
##切换后始终使用npm i xx包,nrm会自动帮助切换
npm i xxx

访问本机7001端口会看到hi egg

##注意:如出现node版本和egg版本冲突无法跑起代码的情况,直接安装报错要求一步步来就能成功运行

3.目录讲解

动手改造目录结构(注意egg是约定大于配置,也就是通过扫描controller下面的文件作为controller,不用手动注册,所以文件名严格按照规范,后期学习的nest.js就需要手动注册,但可以封装成egg这样)

app层--->controller(用户处理restful api的各种接口,功能处理调用service)

app层--->service(用于处理更加繁琐,比如数据库增删查改的方法等等)

app层--->routes(用于路由和controller方法的匹配,比如/user/read对应usercontroller的read方法,这个时候需要对应)

app层--->public(放置一些静态资源)

app层--->middleware(中间件都写这下面)

app层--->extend(延展context的方法和工具类都可以在里面写)

app层--->exception(继承并重写默认的异常处理码)

config--->config.default.js(用于配置安装的插件的一些参数,比如数据库的密码等等,jwt的密码等等)

config--->config.prod.js(内容和config.default.js一样,但是可以分别修改上线的一些参数等等,将测试环境和线上的数据库分开等等)

config--->plugin.js(npm安装的插件,都必须要在这里打开)

4.简单接口编写

首先配置路由

/user/read------>controller的某个方法

  router.get("/user/read", controller.user.read);

controller

"use strict";

const Controller = require("egg").Controller;

class UserController extends Controller {
    async read () {
        const { ctx } = this;
        const data = await this.service.user.findUser();
        ctx.body = data;
    }
}

module.exports = UserController;

service

const Service = require("egg").Service;
class UserService extends Service {
  async findUser() {
    return "indexService";
  }
}

module.exports = UserService;

目录展示,严格为约定大于配置,controller里面直接调用service目录里面的文件方法,都是挂载在中央对象上面的。

image.png

5.配置跨域插件

前端使用axios访问接口的时候会出现跨域的情况,我们可以通过vue cli创建一个前端项项目模拟一下

  1. cli创建前端项目

vue create test

  1. 安装axios请求包

npm i axios --save

  1. 简单的前端请求代码
<script>
import axios from "axios";
export default {
  created() {
    this.init();
  },

  methods: {
    async init() {
      const res = await axios.get("http://localhost:7001/user/read");
      console.log(res);
    },
  },
};
</script>

结果:cors跨域保护

image.png 4. 按照egg-cors插件

npm i egg-cors --save

在plugin.js开启插件

// 配置跨域插件
exports.cors = {
  enable: true,
  package: 'egg-cors',
};

在config.default.js配置跨域允许的白名单,domainWhiteList里面可以配置你所需要的前端请求链接

  // 配置csrf的跨域攻击
  config.security = {
    csrf: {
      enable: false,
    },
    domainWhiteList: [ '*' ],
  };

6.编写helper工具类

在app-extend里面编写helper.js文件,注意名称一定要对,约定大于配置的思想

我们开发一个项目,肯定有很多通用工具类需求封装,比如说时间格式转换相当的常用。

helper.js

const dayJs = require("dayjs")

module.exports = {
    formateDate (date) {
        return dayJs(date).format('DD/MM/YYYY')
    }
}

controller.js

    this.ctx.helper.formateDate('2019-01-25')

7.全局context全局处理

context全局上下文对象,使用this.ctx访问,我们可以ctx扩展方法

例:对于egg中我们controller每次都需要响应请求,但是请求格式每次自己写状态码code字段,返回值msg字段。一是容易写错,二是联调需要改个字段会显得相当的复杂。

'use strict';

module.exports = {
  // 封装响应数据格式
  responseData(data = {}, msg = 'success', code, status = 200) {
    this.status = status;
    this.body = {
      status: code,
      data,
      msg,
    };
  },

controler.js

this.ctx.responseData({a:1},"查询a值成功",200)

8.params和query,body接收参数方式

query

在 URL 中 ? 后面的部分是一个 Query String,这一部分经常用于 GET 类型的请求中传递参数。例如 GET /posts?category=egg&language=node

controller.js

 const query = this.ctx.query;
    // {
    //   category: 'egg',
    //   language: 'node',
    // }

params

GET /projects/1/app/2

controller.js

 this.ctx.params.projectId

body

POST /api/posts HTTP/1.1

controller.js

this.ctx.request.body.title
this.ctx.request.body.content