编写不易,请勿抄袭!
Egg.js 是阿里旗下为数不多的可以让人放心使用的开源项目。
言归正传》》》》
安装 yarn
1.以管理员身份运行终端
2.npm install -g yarn(可能会出现在此程序上禁止运行脚本的情况)
1.set-ExecutionPolicy RemoteSigned 输入 Y
2.查看执行策略 get-ExecutionPolicy
3.yarn create egg --type=simple // 创建 egg 项目
4.yarn install // 安装依赖
5.yarn dev // 运行 egg 项目
项目目录介绍
app/controller // 用于解析用户的输入,处理后返回相应的结果
app/router.js // 用于配置 URL 路由规则
app/service // 用于编写业务逻辑层
config/config.{env}.js // 用于编写配置文件
config/plugin.js // 用于配置需要加载的插件
logs // 项目日志
调试
1. yarn start // 上线运行项目 会一直在后台守护
2. yarn stop // 停掉服务 即使关闭窗口 服务也会在 需要运行指令
3. yarn dev // 开发调试运行专用
控制器和路由
1. 控制台写入函数 所有的函数必须是 async 异步函数声明
2. 然后需要在路由中配置
controller 控制器 // 主要用于解析用户的输入,处理返回相应的
结果
1. 提供接口
2. 渲染页面
3. 代理服务
首先必须按照 egg 的标准,开启 js 严格模式 ‘use strict’
废话不多说,直接上代码
'use strict';
// 从 egg 中获取 Controller
const Controller = require('egg').Controller;
// 声明一个类继承与 Controller
class jsGYController extends Controller {
async index() {
const { ctx } = this;
ctx.body = '<h1>I am jsgy</h1>';
}
async getGirls() {
const { ctx } = this;
await new Promise(resolve => {
setTimeout(() => {
resolve(ctx.body = '<h1>大楠楠,正向你走来</h1>');
}, 5000);
});
}
}
// 将我们写的类暴露出去
module.exports = jsGYController;
单元测试
test 文件下建立 name.test.js 文件
'use strict';
// 获取单元测试的辅助模块 egg-mock
const { app } = require('egg-mock/bootstrap');
// 第一个参数是描述,第二个是回调
describe('jsGY -index', () => {
it('jsgy index page', () => {
return app.httpRequest()
.get('/myJsGY') // 请求测试路径
.expect(200) // 返回页面状态
.expect('<h1>I am jsgy</h1>'); // 对比测试内容
});
it('jsgy getGrils page', async () => {
return app.httpRequest()
.get('/getGirls')
.expect(200)
.expect('<h1>大楠楠,正向你走来</h1>');
});
});
以上都是对 egg 的一些基本了解以及应用,下面切入主题
Get 请求
1. 自由模式接参
通过 url 拼接获取参数
// 自由传参模式(不限制参数,爱传几个传几个)
async getData() {
const { ctx } = this
ctx.body = ctx.query
}
2. 严格模式接参
需要配置路由
router.get('/getData', controller.jsgy.getData); // get 自由模式传参
router.get('/getData2/:name/:age', controller.jsgy.getData2); // get 严格模式传参
然后通过 params 获取参数
// 严格模式传参
async getData2() {
const { ctx } = this
ctx.body = `getData2:大家好我叫${ctx.params.name},我今年${ctx.params.age}岁了`
}
......有待完善
Post 请求
循规蹈矩,配置路由:这次 get 改为 post
router.post('/add', controller.jsgy.add);
然后写 controller
async add(){
const { ctx } = this
ctx.body = {
status: 200,
data: ctx.request.body // post 接参方式
}
}
这样其实我们的一个简单的接口就已经写好了,下面进行接受参数
vsCode 下载 REST Client 插件
config.default.js 文件里面
//关闭 csrf
config.security = {
csrf:{
enable: false
}
}
新建 test.http 文件
POST http://127.0.0.1:7001/add
// 普通的表单方式传递
Content-Type: application/x-www-form-urlencoded
name=jsgy
POST http://127.0.0.1:7001/add
// JSON 传递方式
Content-Type: application/json
{
"name": "小红",
"age": 18
}
Service 要求目录必须在 app 文件夹下
重点来了》》
官方文档给出的解释是用于编写业务逻辑层
但其实说的不够完整,因为编写逻辑在 controller(上文有提到过)
层就已经开始了,那 service 具体干了什么呢?他其实就是.net 三层
架构里面的数据库访问层,说白了就是写数据库交互的
特点/好处
1. 保持 controller 逻辑更加简单
2. 独立性,拥有多个 controller
3. 写测试用例简单
上代码
Service 建立文件
'use strict'
const Service = require("egg").Service
class JsgyService extends Service{
async getGirl(id){
return{
id: id,
name: '小红',
age: 18
}
}
}
module.exports = JsgyService
通过 Controller 调用 Service 写好的函数通过 await 同步方式获取
service 里面的值并且挂载到 router 里面
async getGirls() {
const { ctx } = this;
const res = await ctx.service.jsgy.getGirl('1818')
ctx.body = res
}
通过多个 controller 进行操作
async testGetGirl () {
const { ctx } = this
let id = ctx.query.id
const res = await ctx.service.jsgy.getGirl(id)
ctx.body = res
}
等待数据库。。。。
EJS 引擎
使用 yarn 运行指令:
yarn add egg-view-ejs 引入 ejs 引擎
config/plugin.js 文件中配置 ejs 引擎
'use strict';
// 引入 ejs 引擎
exports.ejs = {
enable: true,
package: "egg-view-ejs"
}
config/config/default.js
// 把默认的.ejs 改成.html
config.view = {
mapping:{
".html": "ejs"
}
}
// 修改默认配置%符(只做知识点展示,不建议修改默认标识符)
config.ejs = {
delimiter: "$"
}
这个时候就可以在 controller 文件中调用 service 的方法,拿到 service
传过来的值并且通过 render 方法传到视图中去
async index() {
const { ctx } = this;
const res = await ctx.service.jsgy.getGirl(20)
await ctx.render("index.html", {
...res,
array: [ '张三', '李四', '王五', '马六' ]
})
}
app 目录下新建 view 目录,view 目录下新建 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>index 页面</title>
<!-- 如果配置了 config 前缀就需要使用配置的前缀编写路径 -->
<link rel="stylesheet" href="assets/css/default.css">
</head>
<body>
<!-- 有点像 jquery 的 load 方法 -->
<$ include jsgy.html $>
<!-- 挂载 render 函数第二个参数传入的匿名对象 -->
<h1>第<$= id$>号,姓名:<$= name$>, 年龄: <$= age$></h1>
<ul>
<$ for(let i = 0; i < array.length; i++) {$>
<li><$=array[i]$></li>
<$}$>
</ul>
</body>
</html>
Jsgy.html
<h1>我是伟大的</h1>
public app/public/** 用于放置静态资源
public 目录下新建一个文件夹 js、css
default.css
body{
color: red;
}
http://127.0.0.1:7001/public/css/default.css 可以访问到上面 css 文件
是因为 node_modules 中有 egg-static 的包
其实也可以自己配置,更改前缀
config/config.default.js 中配置
// 更改 static 的路径前缀(只做知识点展示,不建议更改默认配置)
config.static = {
prefix: "/assets/"
}
之后就可以用 http://127.0.0.1:7001/assets/css/default.css 访问到
Cookie 增删改查
html 文件中通过 js 函数 fetch 去通过访问路由调用 controller 中的方
法
fetch("/add", {
method: "post",
headers: {
"Content-type": "application/json"
}
})
Cookie 存储
// 存储 cookie
ctx.cookies.set('username','Lucy', {
maxAge: 1000*2, // 设置 cookie 过期时间
httpOnly: true, // 是否在客户端获取 cookie true:不可以 false:可以
encrypt: true // 加密 cookie cookie 不能存入中文,但是可以通过加密进行储存
})
Cookie 删除 自动删除等待时间过期,手动删除置为 null
ctx.cookies.set('username', null)
Cookie 查询
ctx.cookies.get('username', {
encrypt: true // 解密 cookie
})
Session
egg 中的 session 其实存在 cookie 中,但是 session 比 cookie 更安全,
所以通常会用 cookie 去保存用户是否登陆,用 session 去保存用户信
息,和登陆信息
配置 session
config.session = {
key: "gy_sess", // 可以修改 session 名称
hettpOnly: false, // 置为 false 就是允许在客户端进行修改 session
maxAge: 1000*60, // 最大响应时间
renew: true // 访问页面时会自动刷新响应时间
}
增加(需要配合 cookie 增加一起使用,不然报错)
ctx.session.username = 'jsgy'
调用和修改就是调用上述方法进行操作,不做展示
删除
ctx.session.username = null
My Sql 数据库
https://www.cnblogs.com/laumians-notes/p/9069498.html
下载 mysql 配置环境变量...具体的按照百度来
新建数据库
My Sql egg.js 连接 MySql
终端运行 yarn add egg-mysql -s 安装 mysql 数据库
Plugin.js 文件
// 配置 mysql
exports.mysql = {
enable: true, // 开启 egg-mysql 插件包
package: "egg-mysql"
}
config.default.js
config.mysql = {
client:{
host: '127.0.0.1', // 服务器地址
port: '3306', // 端口
user: 'root', // 用户
password: 'root', // 密码
database: 'test' // 数据库名
},
app: true, // 是否挂载到 app 下面
agent: false, // 是否挂载到代理上面(默认就是 false,不写也行)
}
至于配置 router、controller 此处不与展示
Service
async getData() {
const app = this.app;
// return app.mysql
// const res = await app.mysql.query('SELECT * FROM `test_one` WHERE age = 18')
const res = await app.mysql.select('test_one'); // 查询 test_one 表
return res;
}
}
如果需要通过 controller 挂载到 router 中 需要将 object 转成 JSON
有关数据库的操作,需要用 try catch 运行,因为数据库操作的时候可
能存在很多问题,需要把出现的问题返回去
数据库增加数据
await app.mysql.insert('test_one', params) // 第一个参数是表名
数据库修改数据
await app.mysql.update('test_one', params)
数据库删除
删除数据库需要传入对象如{ id: 3 }
await app.mysql.delete('test_one', params)