资讯专栏INFORMATION COLUMN

Egg.js学习

xiangchaobin / 485人阅读

摘要:如果需要在构造函数做一些处理,一定要有这句话,才能保证后面的使用。文件夹里面存放工具类引用拿到内置对象也就是进入这个文件页面渲染使用的是页面模板在里面添加添加渲染

egg.js是什么
是一个node.js的后台web框架,类似的还有express,koa

优势:规范插件机制
Egg.js约定了一套代码目录结构
(配置config、路由router、扩展extend、中间件middleware、控制器controller)
规范的目录结构,可以使得不同团队的开发者使用框架写出来的代码风格会更一致,接手成本也会更低。

使用场景

BFF层(前后端之间的中间层)、全栈、SSR(服务端渲染)

目录结构
框架约定的目录
app/router.js 用于配置URL路由规则
app/contorller/** 用于解析用户的输入,处理后返回相应的结果
app/service/** 用于编写业务逻辑层 【可选】
app/middleware/** 用于编写中间件 【可选】
app/service/** 用于框架的扩展 【可选】
...
自定义的目录
app/view/** 用于防止模板文件  【可选】
加载顺序
Egg 将应用、框架和插件都称为加载单元(loadUnit);

在加载过程中,Egg会遍历所有的加载单元,加载时有一点的优先级
· 插件 => 框架 => 应用依次加载
· 依赖方先加载
· 框架按继承顺序加载,越底层越先加载

如有这样一个应用配置了如下依赖

app
| ├── plugin2 (依赖 plugin3)
| └── plugin3
└── framework1
    | └── plugin1
    └── egg

最终的加载顺序为

=> plugin1
=> plugin3
=> plugin2
=> egg
=> framework1
=> app
文件加载顺序
package.json => config => app/extend => app.js => app/service => app/middleware => app/controller => app/router.js
router
首先我们需要配置路由
因为我们在实际的开发中会使用很多路由所以这里我们将路由改成分级的
在app下创建一个router文件夹用来存放路由文件home.js
//app/router/home.js
"use strict"

module exports = app => {
    const { home } = app.controller //获取controller下的home.js
    app.get("/",home.index);
    app.get("/home/param",home.getParam);
    app.get("/home/postParam",home.postParam);
}

// app/router.js
"use strict"
const RouteHome = require("./router/home");
module.exports = {
    const {router, controller} = app;
    RouteHome(app);
}

//app/controller/home.js

"use strict"

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

class HomeController extends Controller {
    async index() {
        await this.ctx.render("/index",{name:"egg"});
    }
    async getParam() {
        let id = await this.ctx.query.id;
        this.ctx.body = id;
    }
    async postParam(){
        let id =  await this.ctx.request.body.id; //获取post参数
        this.ctx.body = id;
    }
}
module exports = HomeController;
controller
我们通过 Router 将用户的请求基于 method 和 URL 分发到了对应的 Controller 上, Controller  负责解析用户的输入,处理后返回相应的结果
框架推荐 Controller 层主要对用户的请求参数进行处理(校验、转换),然后调用对应的 service 方法处理业务,得到业务结果后封装并返回

所有的 Controller 文件都必须放在 app/controller 目录下,可以支持多级目录

访问的时候可以通过目录名级联访问

//在app/controller目录下 新建一个controller
"use strict"

const Controller = required("egg").Controller;

class CustomerController extends Controller {
    async customIndex() {
        //ctx.body 是 ctx.response.body 的简写,不要和 ctx.request.body 混淆了
        this.ctx.body = "this is my controller";
    }
}
module.exports = CustomController;

//在router.js中配置路由(访问时请求的路径)

"use strict"

module.exports = app => {
    //相当于拿到app文件夹下的router和controller
    const {router, controller} = app;
    router.get("/", controller.home.index);
    router.get("/custom",controller.customerController.customIndex);
}
定义的 Controller 类,会在每一个请求访问到 server 时实例化一个全新的对象,而项目中的 Controller 类继承于 egg.Controller,会有下面几个属性挂在 this 上
- this.ctx 框架封装好的处理当前请求的各种便捷属性和方法
- this.app 框架提供的全局对象和方法
- this.service 访问抽象出的业务层 相当于 this.ctx.service
- this.config 运行的配置项
- this.logger 日志
service
业务逻辑层
"use strict";
const Service = require("egg").Service;
class customService extends Service {
    async show(zc, hh) { //异步防阻塞
        return zc + " and " + hh;
    }
}
module.exports = UserService;

//controller代码
"use strict";

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

class CustomController extends Controller {
  async custonIndex() {
    let str = await this.ctx.service.customService.show("zc","hh");
    //这里使用await来获取异步方法的返回值
    this.ctx.body = "this is my controller"+str;
  }
}

module.exports = CustomController;
一个更完整的栗子
// app/router.js
module.exports = app => {
  app.router.get("/user/:id", app.controller.user.info);
};

// app/controller/user.js
const Controller = require("egg").Controller;
class UserController extends Controller {
  async info() {
    const userId = ctx.params.id;
    const userInfo = await ctx.service.user.find(userId);
    ctx.body = userInfo;
  }
}
module.exports = UserController;

// app/service/user.js
const Service = require("egg").Service;
class UserService extends Service {
  // 默认不需要提供构造函数。
  // constructor(ctx) {
  //   super(ctx); 如果需要在构造函数做一些处理,一定要有这句话,才能保证后面 `this.ctx`的使用。
  //   // 就可以直接通过 this.ctx 获取 ctx 了
  //   // 还可以直接通过 this.app 获取 app 了
  // }
  async find(uid) {
    // 假如 我们拿到用户 id 从数据库获取用户详细信息
    const user = await this.ctx.db.query("select * from user where uid = ?", uid);

    // 假定这里还有一些复杂的计算,然后返回需要的信息。
    const picture = await this.getPicture(uid);

    return {
      name: user.user_name,
      age: user.age,
      picture,
    };
  }

  async getPicture(uid) {
    const result = await this.ctx.curl(`http://photoserver/uid=${uid}`, { dataType: "json" });
    return result.data;
  }
}
module.exports = UserService;

// curl http://127.0.0.1:7001/user/1234     
helper
app/extend文件夹里面存放工具类

   //app/extend/getName.js  
   "use strict" 
module.exports = {
    getUserName(id) {
        return list.find(i=>i.id===id).name;
    }
}

//app/extend/helper.js
"use strict" 

const getName = require("./getName");
module.exports = {
    showName() {
        return getName.getUserName("2221");
    }
}

//controller引用helper
"use strict" 

const Controller = require("egg").Controller;
class CustomController extends Controller {
    async customIndex() {
        ////this.ctx.helper拿到helper内置对象也就是进入helper.js这个文件
        this.ctx.body = this.ctx.helper.showName();
    }
}
module.exports = CustomController;
页面渲染
egg.js使用的是nunjucks页面模板
//在config/plugin.js里面添加

"use strict"

 exports.nunjucks = {
        enable: true,
        package: "egg-view-nunjucks"
 }

 //config/config/default.js 添加
 
 "use strict"
 ...
 module.exports = app => {
     ...
     config.view = {
         mapping: {
             ".html": "nunjucks"
         },
         root: path.join(appInfo.baseDir, "app/view")
     }
     ...
     return config;
 }
 
 //app/routes/sign.js
   
   "use strict";
   
    module.exports = (router, controller) => {
        router.get("/sign/modifyPassword", controller.sign.modifyPassword);
    };

 //app/controller/sign.js
 
 "use strict";

  const Controller = require("egg").Controller;
    
  class SignController extends Controller {
        async modifyPassword() {
            const { ctx } = this;
            //渲染view/sign/modifyPassword.html
            await ctx.render("sign/modifyPassword.html");
        }
   }
    
   module.exports = SignController;

   


















文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97733.html

相关文章

  • Egg.js搭建后台服务API

    摘要:因为平常开发都是前后端分离的模式,就想着使用创建后台服务,写一套接口配合其他的项目。复杂数据的处理,比如要展现的信息需要从数据库获取或者是第三方服务的调用。更新用户信息用户信息已更改一个简单的应用结构就是这样,如此便实现了用负责接口服务。 写在前面的话 最近在学习Egg.js,它是阿里推出的基于Koa的node开发框架,为企业级框架和应用而生。Egg.js 的官方文档已经很完善了,想学...

    dailybird 评论0 收藏0
  • Egg.js搭建后台服务API

    摘要:因为平常开发都是前后端分离的模式,就想着使用创建后台服务,写一套接口配合其他的项目。复杂数据的处理,比如要展现的信息需要从数据库获取或者是第三方服务的调用。更新用户信息用户信息已更改一个简单的应用结构就是这样,如此便实现了用负责接口服务。 写在前面的话 最近在学习Egg.js,它是阿里推出的基于Koa的node开发框架,为企业级框架和应用而生。Egg.js 的官方文档已经很完善了,想学...

    idealcn 评论0 收藏0
  • egg.js插件分析

    摘要:前言之前对的整体设计有过自己的理解,在中方便的插件机制也是这个框架的一大亮点,本文主要就是从的插件开始,对后台中的插件机制做一些分析和总结。插件的特点它包含了中间件配置框架扩展等等。插件其余部分的运行原理也是类似的。 前言 之前对egg.js的整体设计有过自己的理解,在egg.js中方便的插件机制也是这个框架的一大亮点,本文主要就是从egg.js的插件开始,对node后台中的插件机制做...

    Kahn 评论0 收藏0
  • egg.js框架开发环境搭建

    摘要:我为了方便直接就指定了淘宝仓库地址运行服务运行项目就比较简单了,运行的命令在浏览器中打开地址,就能看到服务已经启动完成。 传送门:学习node.js服务开发这一篇就够了系列文章 1.创建工程目录 1.1 创建一个文件夹叫 my-egg-application $ mkdir my-egg-application 不熟悉命令行的同学也可以手动创建文件夹 2.初始化项目模板 2.1 进...

    Steve_Wang_ 评论0 收藏0

发表评论

0条评论

xiangchaobin

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<