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:api.map.baidu.com/telematics/… 需要的传参如上所示
还有个重头文件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。