egg.js是什么

是一个node.js的后台web框架,类似的还有express,koa

优势:规范插件机制
Egg.js约定了一套代码目录结构
(配置config、路由router、扩展extend、中间件middleware、控制器controller)
规范的目录结构,可以使得不同团队的开发者使用框架写出来的代码风格会更一致,接手成本也会更低。

使用场景

BFF层(前后端之间的中间层)、全栈、SSR(服务端渲染)

目录结构

框架约定的目录


app/router.js 用于配置URL路由规则
app/contorller/** 用于解析用户的输入,处理后返回相应的结果
app/service/** 用于编写业务逻辑层 【可选】
app/middleware/** 用于编写中间件 【可选】
app/service/** 用于框架的扩展 【可选】
...
自定义的目录
app/view/** 用于防止模板文件 【可选】

加载顺序

Egg 将应用、框架和插件都称为加载单元(loadUnit);

在加载过程中,Egg会遍历所有的加载单元,加载时有一点的优先级
· 插件 => 框架 => 应用依次加载
· 依赖方先加载
· 框架按继承顺序加载,越底层越先加载

如有这样一个应用配置了如下依赖


app
| ├── plugin2 (依赖 plugin3)
| └── plugin3
└── framework1
| └── plugin1
└── egg

最终的加载顺序为


=> plugin1
=> plugin3
=> plugin2
=> egg
=> framework1
=> app

文件加载顺序


package.json => config => app/extend => app.js => app/service => app/middleware => app/controller => app/router.js

router

首先我们需要配置路由
因为我们在实际的开发中会使用很多路由所以这里我们将路由改成分级的
在app下创建一个router文件夹用来存放路由文件home.js


//app/router/home.js
'use strict' module exports = app => {
const { home } = app.controller //获取controller下的home.js
app.get('/',home.index);
app.get('/home/param',home.getParam);
app.get('/home/postParam',home.postParam);
} // app/router.js
'use strict'
const RouteHome = require('./router/home');
module.exports = {
const {router, controller} = app;
RouteHome(app);
} //app/controller/home.js 'use strict' const Controller = require('egg').Controller; class HomeController extends Controller {
async index() {
await this.ctx.render('/index',{name:'egg'});
}
async getParam() {
let id = await this.ctx.query.id;
this.ctx.body = id;
}
async postParam(){
let id = await this.ctx.request.body.id; //获取post参数
this.ctx.body = id;
}
}
module exports = HomeController;

controller

我们通过 Router 将用户的请求基于 method 和 URL 分发到了对应的 Controller 上, Controller 负责解析用户的输入,处理后返回相应的结果
框架推荐 Controller 层主要对用户的请求参数进行处理(校验、转换),然后调用对应的 service 方法处理业务,得到业务结果后封装并返回

  • 所有的 Controller 文件都必须放在 app/controller 目录下,可以支持多级目录
  • 访问的时候可以通过目录名级联访问

//在app/controller目录下 新建一个controller
'use strict' const Controller = required('egg').Controller; class CustomerController extends Controller {
async customIndex() {
//ctx.body 是 ctx.response.body 的简写,不要和 ctx.request.body 混淆了
this.ctx.body = 'this is my controller';
}
}
module.exports = CustomController; //在router.js中配置路由(访问时请求的路径) 'use strict' module.exports = app => {
//相当于拿到app文件夹下的router和controller
const {router, controller} = app;
router.get('/', controller.home.index);
router.get('/custom',controller.customerController.customIndex);
}

定义的 Controller 类,会在每一个请求访问到 server 时实例化一个全新的对象,而项目中的 Controller 类继承于 egg.Controller,会有下面几个属性挂在 this 上


- this.ctx 框架封装好的处理当前请求的各种便捷属性和方法
- this.app 框架提供的全局对象和方法
- this.service 访问抽象出的业务层 相当于 this.ctx.service
- this.config 运行的配置项
- this.logger 日志

service

业务逻辑层



'use strict';
const Service = require('egg').Service;
class customService extends Service {
async show(zc, hh) { //异步防阻塞
return zc + " and " + hh;
}
}
module.exports = UserService; //controller代码
'use strict'; const Controller = require('egg').Controller; class CustomController extends Controller {
async custonIndex() {
let str = await this.ctx.service.customService.show('zc','hh');
//这里使用await来获取异步方法的返回值
this.ctx.body = 'this is my controller'+str;
}
} module.exports = CustomController;

一个更完整的栗子


// app/router.js
module.exports = app => {
app.router.get('/user/:id', app.controller.user.info);
}; // app/controller/user.js
const Controller = require('egg').Controller;
class UserController extends Controller {
async info() {
const userId = ctx.params.id;
const userInfo = await ctx.service.user.find(userId);
ctx.body = userInfo;
}
}
module.exports = UserController; // app/service/user.js
const Service = require('egg').Service;
class UserService extends Service {
// 默认不需要提供构造函数。
// constructor(ctx) {
// super(ctx); 如果需要在构造函数做一些处理,一定要有这句话,才能保证后面 `this.ctx`的使用。
// // 就可以直接通过 this.ctx 获取 ctx 了
// // 还可以直接通过 this.app 获取 app 了
// }
async find(uid) {
// 假如 我们拿到用户 id 从数据库获取用户详细信息
const user = await this.ctx.db.query('select * from user where uid = ?', uid); // 假定这里还有一些复杂的计算,然后返回需要的信息。
const picture = await this.getPicture(uid); return {
name: user.user_name,
age: user.age,
picture,
};
} async getPicture(uid) {
const result = await this.ctx.curl(`http://photoserver/uid=${uid}`, { dataType: 'json' });
return result.data;
}
}
module.exports = UserService; // curl http://127.0.0.1:7001/user/1234

helper

app/extend文件夹里面存放工具类



   //app/extend/getName.js
'use strict'
module.exports = {
getUserName(id) {
return list.find(i=>i.id===id).name;
}
} //app/extend/helper.js
'use strict' const getName = require('./getName');
module.exports = {
showName() {
return getName.getUserName('2221');
}
} //controller引用helper
'use strict' const Controller = require('egg').Controller;
class CustomController extends Controller {
async customIndex() {
////this.ctx.helper拿到helper内置对象也就是进入helper.js这个文件
this.ctx.body = this.ctx.helper.showName();
}
}
module.exports = CustomController;

页面渲染

egg.js使用的是nunjucks页面模板


//在config/plugin.js里面添加 'use strict' exports.nunjucks = {
enable: true,
package: 'egg-view-nunjucks'
} //config/config/default.js 添加 'use strict'
...
module.exports = app => {
...
config.view = {
mapping: {
'.html': 'nunjucks'
},
root: path.join(appInfo.baseDir, 'app/view')
}
...
return config;
} //app/routes/sign.js 'use strict'; module.exports = (router, controller) => {
router.get('/sign/modifyPassword', controller.sign.modifyPassword);
}; //app/controller/sign.js 'use strict'; const Controller = require('egg').Controller; class SignController extends Controller {
async modifyPassword() {
const { ctx } = this;
//渲染view/sign/modifyPassword.html
await ctx.render('sign/modifyPassword.html');
}
} module.exports = SignController;

来源:https://segmentfault.com/a/1190000016378796

Egg.js学习的更多相关文章

  1. Egg.js学习与实战系列 · Post请求`csrf token`问题

    在使用axios请求egg.js封装的post接口时出现missing csrf token 或 invalid csrf token.踩过坑的新手估计不在少数,本篇记录一下解决方法. 问题原因 引用 ...

  2. Egg.js学习与实战系列 · 文件上传配置

    在使用Egg.js搭建文件上传服务时,遇到了几个一般新手都会遇到的坑. 经查阅官方文档,Egg框架中默认使用egg-multipart插件进行文件上传,所以上传文件前需要做相关的配置. 上传文件提示: ...

  3. egg.js 学习之 中间件使用

    1.在框架和插件中使用中间件 编写中间件 我们先来通过编写一个简单的中间件,来看看中间件的写法. // app/middleware/middlewareOne.js // app/middlewar ...

  4. Egg入门学习(三)---理解中间件作用

    Egg是基于koa的,因此Egg的中间件和Koa的中间件是类似的.都是基于洋葱圈模型的. 在Egg中,比如我想禁用某些IP地址来访问我们的网页的时候,在egg.js中我们可以使用中间件来实现这个功能, ...

  5. Egg入门学习(二)---理解service作用

    在上一篇文章 Egg入门学习一 中,我们简单的了解了Egg是什么东西,且能做什么,这篇文章我们首先来看看官网对Egg的整个框架的约定如下,及约定对应的目录是做什么的,来有个简单的理解,注意:我也是按照 ...

  6. Egg入门学习(一)

    一:什么是Egg? 它能做什么?Egg.js是nodejs的一个框架,它是基于koa框架的基础之上的上层框架,它继承了koa的,它可以帮助开发人员提高开发效率和维护成本.Egg约定了一些规则,在开发中 ...

  7. Node.js框架之Egg.js

    Node.js是我前段时间接触的一个JavaScript的服务端语言,感觉还是挺有意思的. 也许有人说,你学这么多,学的过来吗?或者说学的太多,专而不精,有必要这样吗? 其实,我个人认为,自从我进入I ...

  8. egg.js源码解析之render()

    作为阿里的开源node.js框架,我觉得egg.js是很有前途的,故而学之,github上down了一个项目下来(https://github.com/easy-team/egg-vue-webpac ...

  9. egg.js搭建 api设置跨域

    1.egg简述 Egg.js,为企业级框架和应用而生,是阿里开源的企业级 Node.js 框架. 2.特点 Egg 奉行『约定优于配置』,按照一套统一的约定进行应用开发,团队内部采用这种方式可以减少开 ...

随机推荐

  1. vue 使用 sass 或者 less ( vue-cli 3 )

    项目使用 vue-cli 3 在项目中使用 sass npm install sass-loader --save -D cnpm install sass-loader --save -D      ...

  2. python笔记-dumps()与loads()的使用

    json.dumps是将一个Python数据类型列表进行json格式的编码解析, 示例如下: >>> import json #导入python 中的json模块 >>& ...

  3. 分布式文件存储:FastDFS简单使用与原理分析

    引言 FastDFS 属于分布式存储范畴,分布式文件系统 FastDFS 非常适合中小型项目,在我接手维护公司图片服务的时候开始接触到它,本篇文章目的是总结一下 FastDFS 的知识点. 用了 2 ...

  4. 从String中移除空白字符的多种方式!?

    字符串,是Java中最常用的一个数据类型了.我们在日常开发时候会经常使用字符串做很多的操作.比如字符串的拼接.截断.替换等. 这一篇文章,我们介绍一个比较常见又容易被忽略的一个操作,那就是移除字符串中 ...

  5. 16_Python的包package

    1.包的概述 1.包是将模块一文件夹的组织形式进行分组管理的方法,一系列模块进行分类管理有利于防止命名冲突 2.包是一个包含多个模块的特色目录,目录下有一个特色的文件__init__.py 3.包的命 ...

  6. 每日一道 LeetCode (41):阶乘后的零

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

  7. 使用Hint /*+ full(emp)*/ 将索引全扫描改成全表扫描,看cost差别

    索引全扫描的执行计划: SQL> select max(age) from tb_emp04 emp; 已用时间: 00: 00: 00.01 执行计划 -------------------- ...

  8. .NET Core加解密实战系列之——对称加密算法

    简介 加解密现状,编写此系列文章的背景: 需要考虑系统环境兼容性问题(Linux.Windows) 语言互通问题(如C#.Java等)(加解密本质上没有语言之分,所以原则上不存在互通性问题) 网上资料 ...

  9. First-blog:解决mybatis 用mysql进行模糊搜索时,查不了中文问题

    如图:点击小字 按搜索时,出现乱码搜索不了 解决办法:出现乱码问题,一般无非两种 1.是数据库问题 2.是服务器问题 我在MySQL命令行搜索时,中文可以实现,说明时服务器问题 通过修改 tomcat ...

  10. USB URB的status及其代表的意义

    USB URB的status及其代表的意义 平时在处理客户问题时,经常需要分析出现问题时抓取的usbmon log,这个log中有一个字段非常重要:URB Status word,这个字段就是stru ...