这篇文章将会简单的介绍搭建一个简单的Egg.js的应用,以便快速的入门Egg.JS。
这节内容包括:初始化项目,编写 Controller、编写 service。
快速初始化
推荐直接使用脚手架,只需几条简单指令,即可快速生成项目:
$ mkdir egg-example && cd egg-example $ npm init egg --type=simple $ npm i
启动项目:
$ npm run dev $ open localhost:7001
编写 Controller
如果熟悉 Web 开发或 MVC,肯定猜到我们第一步需要编写的是 Controller 和 Router。
// app/controller/home.js const Controller = require('egg').Controller; class HomeController extends Controller { async index() { this.ctx.body = 'Hello world'; } } module.exports = HomeController; // app/controller/new.js const Controller = require('egg').Controller; class NewsController extends Controller { async list() { const dataList = await this.other(); this.ctx.body = { code:0, masg:'news list success', data:dataList }; } async other() { return { list: [ { id: 1, title: 'this is news 1', url: '/news/1' }, { id: 2, title: 'this is news 2', url: '/news/2' } ] } } } module.exports = NewsController; // app/controller/form.js const Controller = require('egg').Controller; class FormController extends Controller { async post(){ this.ctx.body = { msg: this.ctx.response, res: this.ctx.request.body } } } module.exports = FormController;
配置路由映射:
// app/router.js module.exports = app => { // Example get | post router.get('/', controller.home.index); router.get('/list', controller.news.list); router.post('/form', controller.form.post); };
此时目录结构如下:
egg-example ├── app │ ├── controller │ │ └── home.js │ │ └── news.js │ │ └── form.js │ └── router.js ├── config │ └── config.default.js └── package.json
模板渲染
绝大多数情况,我们都需要读取数据后渲染模板,然后呈现给用户。故我们需要引入对应的模板引擎。
安装egg-view-nunjucks来渲染模板。
$ npm i egg-view-nunjucks --save
开启插件:
// config/plugin.js exports.nunjucks = { enable: true, package: 'egg-view-nunjucks' };
// config/config.default.js module.exports = appInfo => { ........ // 添加view配置 config.view = { defaultViewEngine: 'nunjucks', mapping: { '.tpl': 'nunjucks', }, }; return config; };
为列表页编写模板文件,一般放置在 app/view 目录下
<!-- app/view/news/list.tpl --> <html> <head> <title>Hacker News</title> <link rel="stylesheet" href="/public/css/news.css" /> </head> <body> <ul class="news-view view"> {% for item in list %} <li class="item"> <a href="{{ item.url }}">{{ item.title }}</a> </li> {% endfor %} </ul> </body> </html>
添加 Controller 和 Router
// app/controller/news.js const Controller = require('egg').Controller; class NewsController extends Controller { async list() { const dataList = { list: [ { id: 1, title: 'this is news 1', url: '/news/1' }, { id: 2, title: 'this is news 2', url: '/news/2' } ] }; await this.ctx.render('news/list.tpl', dataList); } } module.exports = NewsController; // app/router.js module.exports = app => { const { router, controller } = app; router.get('/', controller.home.index); router.get('/news', controller.news.list); };
编写 service
MySQL
安装egg-mysql:
$ npm i --save egg-mysql
开启插件:
// config/plugin.js exports.mysql = { enable:true, package:'egg-mysql', }
// config/config.default.js module.exports = appInfo => { ........ config.mysql = { // 单数据库信息配置 client: { // host host: 'xx.xxx.xxx.xxx', // 端口号 port: '3306', // 用户名 user: 'root', // 密码 password: 'root', // 数据库名 database: 'testdb', // 时区 timezone:"08:00" }, // 是否加载到 app 上,默认开启 app: true, // 是否加载到 agent 上,默认关闭 agent: false } return config; };
Router:
// app/router.js 'use strict'; /** * @param {Egg.Application} app - egg application */ module.exports = app => { const { router, controller } = app; // Example get | post router.get('/', controller.home.index); router.get('/list', controller.news.list); router.post('/form', controller.form.post); // user CRUD router.get('/userInfo', controller.user.info); // 查 router.get('/addUser', controller.user.add); // 增 router.get('/deleUser', controller.user.dele); // 删 router.get('/updateUser', controller.user.update); // 改 };
Controller:
// app/controller/user.js const Controller = require('egg').Controller; class UserController extends Controller { // 增 ! async add() { // const data = this.ctx.request.body; const data = this.ctx.query; const res = await this.ctx.service.user.add(data); this.ctx.status = 200; this.ctx.body = { status: 200, res: res }; } // 删 ! async dele() { const userId = this.ctx.query.id; const res = await this.ctx.service.user.dele(userId); this.ctx.status = 200; this.ctx.body = { status: 200, res: res }; } // 改 ! async update() { const data = this.ctx.query; const res = await this.ctx.service.user.update(data); this.ctx.status = 200; this.ctx.body = { status: 200, res: res }; } // 查 ! async info() { const userId = this.ctx.query.id; const userInfo = await this.ctx.service.user.find(userId); this.ctx.status = 200; this.ctx.body = { status: 200, res: userInfo }; } } module.exports = UserController;
Service:
// app/service/user.js const Service = require('egg').Service; class UserService extends Service { // 增 ! async add(data) { try { const res = await this.app.mysql.insert('t_user', data); return res } catch (error) { return error } } // 删 ! async dele(uid) { const res = await this.app.mysql.delete('t_user', {user_id: uid}); return res } // 改 ! async update(data) { const options = { where: { user_id: data.user_id } }; const res = await this.app.mysql.update('t_user', data, options); return res } // 查 ! async find(uid) { let user; if (uid) { user = await this.app.mysql.get('t_user', { user_id: uid }); } else { user = await this.app.mysql.select('t_user'); } return user } } module.exports = UserService;
HttpClient
框架在Context中提供了ctx.curl(url,options)和ctx.httpclient来进行 HTTP 请求
// app/service/curl.jsc // app/service/curl.js const Service = require('egg').Service; class CurlService extends Service{ async get(){ const res = await this.ctx.curl('https://httpbin.org/get?foo=bar', { dataType: 'json', // 自动解析 JSON response timeout: 3000, // 3 秒超时 }); return res; } async post(){ const res = await this.ctx.curl('https://httpbin.org/post',{ method: 'POST', // 必须指定 method contentType: 'json', // 通过 contentType 告诉 HttpClient 以 JSON 格式发送 data: { // 传递参数 hello:'world', now: Date.now(), }, dataType: 'json' // 明确告诉 HttpClient 以 JSON 格式处理返回的响应 body }); return res; } async put(){ const res = await this.ctx.curl('https://httpbin.org/put',{ method: 'PUT', contentType: 'json', data: { update: 'foo bar' }, dataType: 'json' }); return res } async delete(){ const res = await this.ctx.curl('https://httpbin.org/delete',{ method: 'DELETE', dataType:'json', }) return res; } } module.exports = CurlService;
目录结构
egg-project ├── package.json ├── app.js (可选) ├── agent.js (可选) ├── app │ ├── router.js │ ├── controller │ │ └── home.js │ ├── service (可选) │ │ └── user.js │ ├── middleware (可选) │ │ └── response_time.js │ ├── schedule (可选) │ │ └── my_task.js │ ├── public (可选) │ │ └── reset.css │ ├── view (可选) │ │ └── home.tpl │ └── extend (可选) │ ├── helper.js (可选) │ ├── request.js (可选) │ ├── response.js (可选) │ ├── context.js (可选) │ ├── application.js (可选) │ └── agent.js (可选) ├── config │ ├── plugin.js │ ├── config.default.js │ ├── config.prod.js │ ├── config.test.js (可选) │ ├── config.local.js (可选) │ └── config.unittest.js (可选) └── test ├── middleware │ └── response_time.test.js └── controller └── home.test.js
如上,由框架约定的目录:
app/router.js 用于配置 URL 路由规则。
app/controller/** 用于解析用户的输入,处理后返回相应的结果。
app/service/** 用于编写业务逻辑层,可选。
app/middleware/** 用于编写中间件,可选。
app/public/** 用于放置静态资源,可选。
app/extend/** 用于框架的扩展,可选。
config/config.{env}.js 用于编写配置文件。
config/plugin.js 用于配置需要加载的插件。
test/** 用于单元测试,具体参见单元测试。
app.js 和 agent.js 用于自定义启动时的初始化工作,可选,具体参见启动自定义。
由内置插件约定的目录:
app/public/** 用于放置静态资源,可选。
app/schedule/** 用于定时任务,可选。
若需自定义自己的目录规范,参见 Loader API
app/view/** 用于放置模板文件,可选,由模板插件约定。
app/model/** 用于放置领域模型,可选,由领域类相关插件约定,如 egg-sequelize。
其实在开发种仔细的查看并理解Egg.js 详细的文档,基本都能解决一些遇到的问题,文档传送门。
还没有评论,来说两句吧...