Eggjs笔记:路由get传值、动态路由、静态资源访问、ejs模板引擎、数据模型Service、方法扩展
路由get传值
官网API:https://eggjs.org/zh-cn/basics/router.html
1 )query的方式
路由
router.get('/news', controller.news.index);
news控制器
async index() {
const { ctx } = this;
ctx.render('news');
// 获取get传值 ?age=10
console.log('query: ' + ctx.query.age);
}
2 ) params的方式
路由
router.get('/newslist/:id', controller.news.list);
news控制器
async list() {
const { ctx } = this;
ctx.body = 'hi, news list';
// 获取get传值
console.log('params: ' + ctx.params.id);
}
动态路由
- 官网API: https://eggjs.org/zh-cn/basics/controller.html
egg-view-ejs 的使用
- github: https://github.com/eggjs/egg-view-ejs
- 配置
- config/plugin.js
module.exports = { ejs: { enable: true, package: 'egg-view-ejs', }, };
- config/config.default.js
// 配置ejs 建议版本 config.view = { mapping: { '.html': 'ejs' } };
- controller中使用
// 定义渲染数据 const msg = 'ejs'; const list = [ '111', '222', '333' ]; await ctx.render('news', { msg, list, }); // 注意这里和koa一样,异步渲染
- view中编写html, 如news.html
<h3>这是一个新闻 == <%=msg%></h3> <ul> <% for(var i=0; i < list.length; i++) { %> <li><%=list[i]%></li> <%}%> </ul>
静态资源的访问
<img width="200" src="/public/images/2.jpg" />
数据模型 Model(service)
抽离数据,此处演示,不从数据库读取
services.news
'use strict';
const Service = require('egg').Service;
class NewsService extends Service {
async getList() {
// 定义渲染数据
const list = [ '111', '222', '333' ];
return list;
}
}
module.exports = NewsService;
在controller中应用
async index() {
const { ctx } = this;
// ctx.body = 'hi, news';
// 定义渲染数据
const msg = 'hello ejs';
const list = await this.service.news.getList();
await ctx.render('news', {
msg,
list,
}); // 注意这里和koa一样,异步渲染
}
-
根据官网中关于Controller,在this属性上的东西, 具体使用很方便
此外 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 对象记录的日志,在日志前面会加上打印该日志的文件路径,以便快速定位日志打印位置。 -
我们的服务service可以在控制器中调用,也可以在service中相互调用,模块划分,非常方便
-
但是服务不能调用控制器,控制器也不能相互调用
-
服务的命名规则:
- Service 文件必须放在 app/service 目录,可以支持多级目录,访问的时候可以通过目录名级联访问
app/service/biz/user.js => ctx.service.biz.user (推荐写法) app/service/sync_user.js => ctx.service.syncUser app/service/HackerNews.js => ctx.service.hackerNews
- 一个 Service 文件只能包含一个类, 这个类需要通过 module.exports 的方式返回。
- Service 需要通过 Class 的方式定义,父类必须是 egg.Service。
- Service 不是单例,是 请求级别 的对象,框架在每次请求中首次访问 ctx.service.xx 时延迟实例化,所以 Service 中可以通过 this.ctx 获取到当前请求的上下文
- Service 文件必须放在 app/service 目录,可以支持多级目录,访问的时候可以通过目录名级联访问
方法扩展
-
https://eggjs.org/zh-cn/basics/extend.html
-
框架提供了多种扩展点扩展自身的功能:
- Application
- Context
- Request
- Response
- Helper
- 在开发中,我们既可以使用已有的扩展 API 来方便开发,也可以对以上对象进行自定义扩展,进一步加强框架的功能
以下对Application,Context,Request,Helper进行测试,在目录app/extend下新建四个文件:application.js、context.js、helper.js、request.js
1 ) Application
application.js编码
'use strict';
/*
* 外部通过 this.app.foo() 来调用
*/
module.exports = {
foo() {
// this 就是 app 对象,在其中可以调用 app 上的其他方法,或访问属性
// console.log(this);
return this.config.api;
},
};
2 ) Context
context.js编码
'use strict';
/*
* 外部通过 this.ctx.foo() 来调用
*/
module.exports = {
getHost() {
// this 就是 app 对象,在其中可以调用 app 上的其他方法,或访问属性
// console.log(this);
return this.request.host;
},
};
3 ) Request
'use strict';
/*
* 外部通过 来调用
*/
module.exports = {
// 时间戳转换时间
foo() {
// console.log(this); // 这里是request对象
return 'req host: ' + this.header.host;
},
};
4 ) helper.js
'use strict';
/*
* 外部通过 this.helper.formatTime() 来调用
*/
// 扩展里面引入第三方模块
const sd = require('silly-datetime');
module.exports = {
// 时间戳转换时间
formatTime(param) {
// 这里是10位的日期,*1000
return sd.format(param * 1000, 'YYYY MM DD HH:mm');
},
// 获取信息
getHelperData() {
return 'I"m helper data!';
},
};
5 ) 最终调用测试,在app/controller/home.js中
async index() {
const { ctx } = this;
await ctx.render('index');
// 测试调用extend里面扩展的application
console.log(this.app.foo());
// 测试调用extend里面扩展的context
console.log(this.ctx.getHost());
// 测试调用extend里面扩展的helper方法 egg框架把helper挂载到了context下面
console.log(this.ctx.helper.getHelperData());
// 测试调用extend里面扩展的request方法
console.log(this.ctx.request.foo());
}
特别的,在模板文件 view/news.html中,对时间的处理helper.formatTime
,但是这种客户端处理时间戳的方式可能会有很难解决的兼容问题
<ul>
<% for(var i=0; i < list.length; i++) { %>
<li>
<a href="/newscontent?aid=<%=list[i].aid%>"><%=list[i].title%></a> <span>---<%=helper.formatTime(list[i].dateline)%></span>
</li>
<%}%>
</ul>
上一篇: echarts快速上手(一)
下一篇: kmeans聚类图像的像素并可视化