一、Egg.js 是什么?官网
- Egg.js 是《阿里旗下产品》基于 Node.js 和 Koa 是一个 Nodejs 的企业级应用开发框架。 可以帮助发团队和开发人员降低开发和维护成本。
- Express 和 Koa 是 Node.js 社区广泛使用的框架,简单且扩展性强,非常适合做个人项 目。但框架本身缺少约定,标准的 MVC 模型会有各种千奇百怪的写法。Egg 按照约定进行 开发,奉行『约定优于配置』,团队协作成本低。
- Egg.js 基于 Es6、Es7 以及 Typescript、Koa2 使得 Nodejs 具有更规范的开发模式、更低 的学习成本、更优雅的代码、更少的开发成本、更少的维护成本。为企业级框架而生。
二、 快速上手
1.安装 egg 脚手架以及使用 egg-init 创建项目
$ npm i egg-init -g
$ egg-init egg-example --type=simple
$ cd egg-example
$ npm i
启动项目:
$ npm run dev
$ open localhost:7001
2、Egg.js 目录结构介绍
Egg.js 目录约定规范
3、Vscode+Egg 开发工具配置
4、配置路由
- 在router.js中先配置访问路劲
"use strict";
module.exports = (app) => {
const { router, controller } = app;
router.get("/", controller.home.index);
router.get("/admin", controller.admin.index);
router.get("/news", controller.news.index);
router.get("/newslist/:id", controller.news.newslist);
router.get("/newscontent", controller.news.content);
};
- 在Controller进行对应路由的编写
'use strict';
const Controller = require('egg').Controller;
class NewsController extends Controller {
async index() {
const { ctx } = this;
ctx.body = 'hi, egg New';
}
async content() {
const { ctx } = this;
console.log(ctx.query);
ctx.body = '新闻详情';
}
}
module.exports = NewsController;
'use strict';
const Controller = require('egg').Controller;
class NewsController extends Controller {
async index() {
const { ctx } = this;
ctx.body = 'hi, egg New';
}
//获取get传值
async content() {
const { ctx } = this;
console.log(ctx.query);
ctx.body = '新闻详情';
}
//获取params传值
async newslist() {
const { ctx } = this;
console.log(ctx.params);
ctx.body = '新闻列表';
}
}
module.exports = NewsController;
4、egg-view-ejs 的使用
- 安装
npm i egg-view-ejs --save
- 找到 {app_root}/config/plugin.js
exports.ejs = {
enable: true,
package: 'egg-view-ejs',
};
- // {app_root}/config/config.default.js
//配置模板引擎
config.view = {
mapping: {
'.html': 'ejs',
},
};
5、controller
class NewsController extends Controller {
async index() {
const { ctx } = this;
// ctx.body = 'hi, egg New';
let ejs= 'ejs'
await ctx.render('news',{ejs})
}
}
6、渲染页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
新闻页面
<h2><%=ejs%></h2>
</body>
</html>
7、将数据抽到Service层
Service
const { Service } = require("egg");
class NewService extends Service {
async getNewsList() {
const list = ["1111", "2222", "333"];
return list;
}
}
module.exports = NewService;
Controller
const {Controller} = require('egg');
class NewsController extends Controller {
async index() {
const { ctx,service } = this;
let list = await service.news.getNewsList()
await ctx.render('news',{list})
}
}
定义的 Controller 类,会在每一个请求访问到 server 时实例化一个全新的对象,而项目中的 Controller 类继承于 egg.Controller,会有下面几个属性挂在 this 上。
- this.ctx: 当前请求的上下文 Context 对象的实例,通过它我们可以拿到框架封装好的处理当前请求的各种便捷属性和方法。
- this.app: 当前应用 Application 对象的实例,通过它我们可以拿到框架提供的全局对象和方法。
this.service:应用定义的 Service,通过它我们可以访问到抽象出的业务层,等价于 this.ctx.service 。 - this.config:应用运行时的配置项。
- this.logger:logger 对象,上面有四个方法(debug,info,warn,error),分别代表打印四个不同级别的日志,使用方法和效果与 context logger 中介绍的一样,但是通过这个 logger 对象记录的日志,在日志前面会加上打印该日志的文件路径,以便快速定位日志打印位置。
7、框架扩展
扩展方式
框架会把 app/extend/application.js 中定义的对象与 Koa Application 的 prototype 对象进行合并,在应用启动时会基于扩展后的 prototype 生成 app 对象。
- 例如,我们要增加一个 app.foo() 方法:
// app/extend/application.js
module.exports = {
foo(param) {
// this 就是 app 对象,在其中可以调用 app 上的其他方法,或访问属性
},
};
在Controller中调用
this.ctx.foo()
8、中间件(Middleware)
屏蔽指定ip
app\middleware\forbidip.js
// options: 中间件的配置项,框架会将 app.config[${middlewareName}] 传递进来。
// app: 当前应用 Application 的实例。
module.exports = (options, app) => {
//返回一个异步方法
return async function forbidIp(ctx, next) {
//获取要屏蔽的ip 1.从数据库获取,2.从参数获取
//要屏蔽的ip
// var forbidip = "127.0.0.1";
//获取客户端的ip
if (ctx.request.ip == options.forbidips) {
ctx.status = 403;
ctx.body = "您的ip已经被屏蔽";
} else {
await next();
}
};
};
配置中间件config\config.default.js
"use strict";
module.exports = (appInfo) => {
const config = (exports = {});
// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + "_1532656413112_8161";
// 中间件配置
config.middleware = ["printdata", "forbidip"];
config.forbidip = {
forbidips: "127.0.0.1",
};
//配置ejs模板引擎
config.view = {
mapping: {
".html": "ejs",
},
};
//配置公共的api
config.api = "http://www.phonegap100.com/";
return config;
};
效果
9、Post提交数据
默认报错
官网说明
设置全局变量
注意:记得在全局变量中引入
10、Cookie
通过 ctx.cookies,我们可以在 controller 中便捷、安全的设置和读取 Cookie。
ctx.cookies.set(key, value, options)
class HomeController extends Controller {
async add() {
const ctx = this.ctx;
//获取
let count = ctx.cookies.get('count');
count = count ? Number(count) : 0;
//设置
ctx.cookies.set('count', ++count);
ctx.body = count;
}
}
11、Session
-
session是另-种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而session保存在服务器.上。
-
当浏览器访问服务器并发送第一-次请求时 , 服务器端会创建一个session对象,生成一个类似于key,value的键值对,然后将key(cookie)返回到浏览器(客户)端浏览器下次再访问时,携带key(cookie),找到对应的session(value)。
class HomeController extends Controller {
async fetchPosts() {
const ctx = this.ctx;
// 获取 Session 上的内容
const userId = ctx.session.userId;
const posts = await ctx.service.post.fetch(userId);
// 修改 Session 的值
ctx.session.visited = ctx.session.visited ? (ctx.session.visited + 1) : 1;
ctx.body = {
success: true,
posts,
};
}
}