Egg.js随学随记

1. Egg.js安装

1.1 安装Egg.js

cnpm install egg-init -g

采用全局安装,而非--save,原因有待后面分解。

1.2 在VS Code下安装Egg.js代码提示

file

2. 初始化Egg.js项目

egg-init project_name

如果这样输入命令,则在命令运行过程中会出现一个选项,让你选择所要创建的项目类型:
file
这里我选择新建一个simple项目,安装完成后,会弹出安装依赖和启动项目的提示命令:
file
这里要注意,创建项目的是新建一个文件夹。所以请合理的安排安装目录。
已经学到Egg.js了,各种cnpm的命令是什么意思应该很清楚了吧?
所以接下来安装依赖:

cnpm install

安装完成后,启动项目:

npm run dev

3. Egg.js目录约定

3.1 官方约定。

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

3.2 MVC架构

我们的开发都在app目录下完成,Egg.js使用MVC架构,与文件夹对应关系如下:

├── app
|   ├── router.js(路由规则)
│   ├── controller(Controller)
│   |   └── home.js
│   ├── service (Model)
│   |   └── user.js
│   ├── middleware (中间件)
│   |   └── response_time.js
│   ├── public (静态资源)
│   |   └── reset.css
│   ├── view (View)
│   |   └── home.tpl
│   └── extend (扩展方法)
│       ├── helper.js (可选)
│       ├── request.js (可选)
│       ├── response.js (可选)
│       ├── context.js (可选)
│       ├── application.js (可选)
│       └── agent.js (可选)

4. 一个mini的Egg.js项目

4.1 安装egg-view-ejs插件

cnpm install ejs --save
cnpm install egg-view-ejs --save

安装插件后需要配置两个文件:
文件1:/config/plugin.js

'use strict';

/** @type Egg.EggPlugin */
module.exports = {
  // had enabled by egg
  // static: {
  //   enable: true,
  // }
  ejs:{//增加部分
      enable: true,
      package: 'egg-view-ejs',
    }
};

文件2:/config/config.default.js

/* eslint valid-jsdoc: "off" */

'use strict';

/**
 * @param {Egg.EggAppInfo} appInfo app info
 */
module.exports = appInfo => {
  /**
   * built-in config
   * @type {Egg.EggAppConfig}
   **/
  const config = exports = {};

  // use for cookie sign key, should change to your own and keep security
  config.keys = appInfo.name + '_1582681748898_3732';

  // add your middleware config here
  config.middleware = [];

  // add your user config here
  const userConfig = {
    // myAppName: 'egg',
  };

  config.view = {//增加部分
    mapping: {
      '.html': 'ejs',
    },
  };

  return {
    ...config,
    ...userConfig,
  };
};

4.2 文件结构

├── app
|   ├── router.js
│   ├── controller
│   |   └── news.js
│   ├── service
│   |   └── news.js
│   ├── public
│       └── images
│              └── welcome.gif
│   ├── view
│       └── index.html
│       └── content.html
│       └── list.html

4.3 文件代码

4.3.1 router.js

'use strict';

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const { router, controller } = app;
  router.get('/', controller.news.index);
  router.get('/list', controller.news.list);
  router.get('/content/:newsid/:newscategory', controller.news.content);
};

4.3.2 service/news.js 模拟从数据库获取并返回数据

'use strict';

const Service = require("egg").Service;

class NewsService extends Service {
    async getNewsList(){
        //模拟从数据库模拟数据
        var dbData = ["A news about Tom","Jerry's news is cooler!","Popeye finally married Olive!"];
        return dbData;
    }
}

module.exports = NewsService;

4.3.3 controller/news.js 处理业务逻辑

'use strict';

const Controller = require('egg').Controller;

class NewsController extends Controller {
  async index() {
    const { ctx } = this;
    await ctx.render("index.html");
  }
  async list() {
    const { ctx } = this;
    var newsList = await ctx.service.news.getNewsList();
    await ctx.render("list.html",{
        newsList:newsList
    });
  }
  async content() {
    const { ctx } = this;
    var getInfo = ctx.query;
    var paraInfo = ctx.params;

    var name = getInfo.name;
    var level = getInfo.level;

    var newsId = paraInfo["newsid"];
    var newsCategory = paraInfo["newscategory"];

    await ctx.render("content.html",{
        name:name,
        level:level,
        newsid:newsId,
        newscategory:newsCategory
    });
  }
}

module.exports = NewsController;

4.3.4 view/三个文件

文件1:view/index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <h1>你好!欢迎进入迷你新闻系统!</h1>
        <h2>在Egg.js中,静态资源直接使用资源目录路径引用即可!比如下面的图片</h2>
        <img src="/public/images/welcome.gif" >
        <h3><a href="/list">点我进入新闻列表</a></h3>
    </body>
</html>

文件2:view/list.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <h1>新闻列表</h1>
        <ul>
            <%for(let i=0;i<newsList.length;i++){%>
            <li><%=newsList[i]%></li>
            <%}%>
        </ul>

        <h3>
            <a href="/content/6/HotNews?name=Tom&level=3">
                这条新闻通过参数和动态路由传递数据,链接地址是:    /content/6/HotNews?name=Tom&level=3
            </a>
        </h3>
    </body>
</html>

文件3:view/content.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <h3>Name is: <%=name%></h3>
        <h3>Level is: <%=level%></h3>
        <h3>News ID is: <%=newsid%></h3>
        <h3>News Category is: <%=newscategory%></h3>
    </body>
</html>