Egg.js是一个基于Koa开发的Node.js框架。为企业级框架和应用而生。
官网介绍,Egg
奉行『约定优于配置』,按照一套统一的约定进行应用开发,团队内部采用这种方式可以减少开发人员的学习成本。
😊 约定优于配置理念,也是为了更好的拧螺丝的手段。不过挺好用~
环境搭建
推荐使用脚手架搭建:
$ mkdir egg-example && cd egg-example
$ npm init egg --type=simple
$ npm i
复制代码
启动项目:
$ npm run dev
$ open http://localhost:7001
复制代码
当然,推荐使用yarn
进行包管理。
此时,在http://localhost:7001
或者http://127.0.0.1:7001
地址的页面上,你会看到egg 的 say hi
提示。
基本概念什么的,感兴趣的话,直接去它的官网了解。
我们直接来实现一个mvc
的后端渲染项目 - 天气预报
天气预报
我们使用的egg
版本号是 ^2.15.1
~
为啥要说明这里的版本号?因为可能config里面的写法不同~无伤大雅
前期准备
- 我们先关闭crsf,避免在进行表单提交的时候报错
// config/config.default.js
// 关闭csrf
config.security = {
csrf: false
}
复制代码
- 视图模版引擎我们不使用官网推荐的
nunjucks
,而是使用egg-view-ejs
插件。选择自己拿手的就行。
通过npm install egg-view-ejs --save
,进行相关的配置:
// config/plugin.js
// 引入第三方插件ejs
ejs: {
enable: true,
package: 'egg-view-ejs',
}
// config/config.default.js
// 处理视图
config.view = {
mapping: {
'.html': 'ejs',
},
};
复制代码
⚠️ 注意:处理视图文件的配置时候,我们选择
.html
的后缀,比较适合前端习惯。当然,你可以保留.ejs
的后缀。
- 选择自己熟悉的IDE,安装相关插件进行信息提示
这里我还是选择了Visual Studio Code,安装eggjs
插件。
接下来我们将集中在app
文件夹内完成✅这个天气预报小项目。
weather-project
├── app
| ├── controller
| | └── weather.js
| ├── public
| | └── weather.css
| ├── service
| | └── weather.js
| ├── view
| | └── weather.html
| └── router.js
.
复制代码
开发进程
我们一一来说,你感兴趣的话,可以一一复制代码进行尝试~🉑️
页面骨架搭建:
<!--view/weather.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气预报</title>
<link rel="stylesheet" href="https://unpkg.com/ant-design-vue@1.6.4/dist/antd.min.css"/>
<link rel="stylesheet" href="/public/weather.css" />
</head>
<body>
<div id="app">
<a-result>
<template slot="icon">
<a-icon type="cloud"/>
</template>
<template slot="title">
<b>天气预报 - <%= data.currentCity %></b>
</template>
</a-result>
<div class="search">
<form action="http://127.0.0.1:7001/weather" method="POST">
<input type="text" name="location" placeholder="请输入城市,如:广州" required>
<a-button type="primary" html-type="submit">查询</a-button>
</form>
</div>
<div class="main">
<% if(data.code === -1) { %>
<a-alert style="width: 260px; margin: 0 auto;" :message="`<%= data.msg %>`" banner />
<% } else { %>
<a-timeline mode="alternate">
<% for(let i =0; i < data.weather_data.length; i++) {%>
<a-timeline-item :color="`<%= i % 2 == 0 ? 'blue' : 'green'%>`">
<p style="margin-bottom: 4px;"><%= data.weather_data[i].date %></p>
<a-tag color="orange"><%= data.weather_data[i].temperature %></a-tag>
<p style="margin-top: 4px;"><%= data.weather_data[i].wind %></p>
</a-timeline-item>
<% } %>
</a-timeline>
<% } %>
</div>
</div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ant-design-vue/1.6.4/antd.min.js"></script>
<script type="text/javascript">
(function(){
new Vue({
el: '#app'
})
})()
</script>
</body>
</html>
复制代码
页面展示润色:
# public/weather.css
*{
padding: 0;
margin: 0;
}
#app .search{
text-align: center;
}
#app .search input{
outline: none;
width: 200px;
height: 34px;
border-radius: 4px;
padding: 0 12px;
border: 1px solid #ddd;
}
#app .main{
margin: 20px 0;
}
复制代码
我们是使用的MVC
模式,怎么缺得了controller和service
呢。当然,service
是可选的,但是不建议省略~
controller
部分:
// controller/weather.js
'use strict';
const Controller = require('egg').Controller;
class WeatherController extends Controller {
async getWeather() {
const { ctx, service } = this;
const data = await service.weather.getWeather('广州')
await ctx.render('weather', { data })
}
async postWeather() {
const { ctx, service } = this;
const location = ctx.request.body.location
const data = await service.weather.getWeather(location)
await ctx.render('weather', { data })
}
}
module.exports = WeatherController;
复制代码
service
部分:
// service/weather.js
'use strict'
const Service = require('egg').Service
class WeatherService extends Service {
async getWeather(location) {
const { app } = this
const data = await app.curl('https://api.map.baidu.com/telematics/v3/weather', {
data: {
ak: 'zVo5SStav7IUiVON0kuCogecm87lonOj',
output: 'json',
location
},
dataType: 'json'
});
if(data.data.error === 0) {
return data.data.results && data.data.results[0]
} else {
return {
code: -1,
msg: '请输入正确的城市名字'
}
}
}
}
module.exports = WeatherService
复制代码
⚠️ 这里我们是使用了百度提供的天气查询API:https://api.map.baidu.com/telematics/v3/weather 需要的传参如上所示
还有个重头文件router.js
,我们的页面是根据这个路由文件,通过controller
来控制不同视图的展示。
// router.js
module.exports = app => {
const { router, controller } = app;
// weather
router.get('/weather', controller.weather.getWeather)
router.post('/weather', controller.weather.postWeather)
};
复制代码
最终效果
- 输入正确的城市进行搜索
- 输入不正确的城市进行搜索
后话
这次的讲解没有引入数据库,下篇文章讲解的是前后端分离的eggjs
项目,会将数据库也引入。更多的项目详见Jimmy Blogs。
源码
源码请见仓库egg demo ~
本文同步分享在 博客“”(JueJin)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。