Egg.js 中 Controller 的使用

如果需要了解Controller ,就得知道什么是mvc。

MVC概述

什么是mvc,这个概念,我相信绝大部分人肯定是了解的。MVC是模型(model)- 视图(view)- 控制器(controller)的缩写。MVC是一种软件设计规范,主要作用就是逻辑拆分:

  • 视图为用户展示数据
  • 控制器用来处理用户输入
  • 模型用户数据处理

ps:这一整套流程实际上是一个闭环,你可以这么去理解,就是用户输入给控制器,然后控制器将用户输入的指令和数据传递给业务组件,业务组件进行业务逻辑判断,数据库存取,将要展示的数据返回到视图,用户得到了反馈,在进行下一步的操作。

Egg中的控制器(controller)

  • 直接响应数据或渲染模板
  • 接受用户输入
  • 与路由器建立对应关系

this.ctx可以获取到当前请求的上下文对象,通过此对象可以便捷的获取到请求与响应的属性与方法。

我们可以拿最初的模板案例来解析,controller文件夹下面的home.js文件:

'use strict'; //严格模式

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

class HomeController extends Controller { //定义一个新的类去继承Controller类
  async index() {
    const { ctx } = this;
    ctx.body = '你好egg';
  }
}

module.exports = HomeController; //暴露HomeController

这个严格模式,写和不写都可以,没必要说一定要写,这个也不是egg特有的,因为egg已经给我们封装好了控制器的方法,所以我们只需要调用就好了,然后继承暴露出来,最简单的一个控制器我们就写好了。

接下来,尝试写一个水果控制器,首先要在controller文件夹下创建fruits.js,然后我们模仿home.js进行编写。

'use strict'; //严格模式

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

class FruitsController extends Controller {
  async index() {
    this.ctx.body = '我是一个水果列表'
  }
}
module.exports = FruitsController

此时,我们写完,想要去访问这个页面,肯定是需要路由去访问的,所以,我们需要去编写router.js这个文件,来访问我们刚刚写的水果页面。

'use strict';

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const { router, controller } = app;
  router.get('/', controller.home.index);
  router.get('/fruits', controller.fruits.index);
};

通过这个代码,我们可以看出来,这个是通过暴露一个函数,这个app是一个形参,是egg应用里的一些实例。

然后通过结构赋值的方法,我们拿到了,router和controller这两个对象。

然后通过路由的get方法去规定跳转的路由地址,以及展示的是controller目录下面的home文件里的index方法。

所以我们访问地址是’/‘看到的就是’hi,egg’,所以我们模仿一下,加上router.get(‘/fruits’, controller.fruits.index); 就能通过访问’/fruits’实现访问上面写的水果页面了。

Egg.js 中 Controller 的使用_第1张图片

通过路由传递参数

  • 获取query参数
  • 获取params参数

获取query参数的get请求方法

我们在控制器里靠一个属性去获取get请求的query,this.ctx.request.query,然后我们只要在url后面拼上传递的数据,就能获取到了,http://127.0.0.1:7001/fruits?index=100

'use strict'; //严格模式

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

class FruitsController extends Controller {
  async index() {
    let query = this.ctx.request.query
    this.ctx.body = `传递的index的值是${query.index}`
  }
}
module.exports = FruitsController

Egg.js 中 Controller 的使用_第2张图片

params参数的get请求方法

首先我们要在router.js里面加上一行router.get(‘/fruits/:id’, controller.fruits.getId),我们重新写一个getId的方法。

async getId() {
    let id = this.ctx.params.id
    this.ctx.body = `传递的id的值是${id}`
}

然后我们只要在url后面加上’/100’就能获取到了,http://127.0.0.1:7001/fruits/100

Egg.js 中 Controller 的使用_第3张图片

拓展:那么如果你想传多个参数,就继续往后面拼就可以了router.get(‘/fruits/:id/:title’, controller.fruits.getId),拿的话,也和上面一样let title = this.ctx.params.title。

query和params的post请求

说完了query以及params的get请求呢,接下来就是query和params的post请求了,这个稍微难一点。获取post请求参数:this.ctx.request.body。

举个例子实现,表单提交是post请求,我们可以通过实现表单提交来获取post的参数,那么,我们可以通过提交表单,插入数据到列表里面。

第一步:要创建数组,和类同级

let fruitList = ["香蕉", "苹果", "西瓜"]

第二步:有了数组,我们就需要一个页面去展示这个数组

async getList() {  //获取水果列表
    this.ctx.body = fruitList
}
router.get('/fruitList', controller.fruits.getList);

Egg.js 中 Controller 的使用_第4张图片

第三步:构建表单页面

async createPage() {   //提交表单
    this.ctx.body = `
    
`
}
router.get('/createPage', controller.fruits.createPage);

Egg.js 中 Controller 的使用_第5张图片

第四步:我们需要输入,然后将输入的内容插入到水果列表里面,首先我们要修改一下createPage方法,加入请求方法为post,提交的地址也要加上。

async createPage() {
    this.ctx.body = `
    
`
} async creatFruit() { //获取提交的水果数据 let fruit = this.ctx.request.body this.ctx.body = fruit }
router.post('/creatFruit', controller.fruits.creatFruit);

第五步:输入水果,提交表单,发现,页面显示403

Egg.js 中 Controller 的使用_第6张图片

之所以有这个情况,是因为CSRF指跨站请求伪造,Egg中对post请求做了一些安全验证,可以在config.default.js文件中,通过下面的设置验证。

config.security = {
      csrf:{
          enable:false
    }
}

配置好这个,我们再次输入水果,再次点击提交,此时,我们成功跳转到了’/createFruit’页面

Egg.js 中 Controller 的使用_第7张图片

第六步:也就是最后一步,我们需要提交跳转的页面,将数据插入到原先的列表里面去

async creatFruit() {
    let fruit = this.ctx.request.body
    fruitList.push(fruit.fruitName)
    this.ctx.body = '添加成功'
}

此时,我们输入提交会出现 ‘添加成功’的字样,然后我们在跳转会’/fruitList’就会看到输入的内容已经被插入了

Egg.js 中 Controller 的使用_第8张图片

//fruits.js
'use strict'; //严格模式

const Controller = require('egg').Controller; //Controller类
let fruitList = ["香蕉", "苹果", "西瓜"]
class FruitsController extends Controller {

  //index方法  用于获取query的get请求参数
  async index() {
    let query = this.ctx.request.query
    this.ctx.body = `传递的index的值是${query.index}`
  }

  //getId方法  用于获取params的get请求参数
  async getId() {
    let id = this.ctx.params.id
    let title = this.ctx.params.title
    this.ctx.body = `传递的id的值是${id},传递的title是${title}`
  }

  //getList方法  用于展示水果列表
  async getList() {
    this.ctx.body = fruitList
  }

  //createPage方法  用于表单提交页面
  async createPage() {
    this.ctx.body = `
    
`
} //插入提交的水果 async creatFruit() { let fruit = this.ctx.request.body fruitList.push(fruit.fruitName) this.ctx.body = '添加成功' } } module.exports = FruitsController
//router.js
'use strict';

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const {
    router,
    controller
  } = app;
  router.get('/', controller.home.index); //默认页
  router.get('/fruits', controller.fruits.index);
  router.get('/fruits/:id/:title', controller.fruits.getId)
  router.get('/fruitList', controller.fruits.getList);
  router.get('/createPage', controller.fruits.createPage);
  router.post('/creatFruit', controller.fruits.creatFruit);
};

到这里,post的请求方法拿参数完成了,不过,往回看路由,会发现,我们写的很多,get写一个,post写一个,如果后面说,一个地址里面,引入了好多的方法,那会越写越多,所以这里egg为了简单写法,给出了新的形式。

RESTful风格的URL定义

restful风格的url可以简化路由文件
格式:app.router.resources(‘routerName’, ‘pathMatch’, controller)

router.resources('posts','/api/posts',controller.posts) //一个方法同时定义增删改查

Egg.js 中 Controller 的使用_第9张图片

我们来简化一下之前的路由,全部隐藏,你可以删除,然后写上

router.resources('fruits', '/fruits', controller.fruits)

根据表格的对对照关系,我们将fruits.js修改一下

async index() {
    this.ctx.body = fruitList
}

async new() {
    this.ctx.body = `
    
`
} async create() { let fruit = this.ctx.request.body fruitList.push(fruit.fruitName) this.ctx.body = '添加成功' }

首先这个index方法,对应表格里面的get请求,就把之前的getList的方法内容移到index方法里面

就是index方法专门去获取水果列表,表里对应的new方法,放表单的提交内容

有一点要注意,就是我们提交时候的action地址要变成router.js里面写的地址,creat方法对应的是post请求,所以我们放拿到参数的一系列操作。然后我们回到页面,在地址栏上输入’/fruits’,就能看到列表,输入’/fruits/new’,就会来到提交表单页面。

最后我们完善一下这个demo,添加成功,返回到水果列表的页面,我们只需要用this.ctx.redirect(‘/fruits’)就能重定向到水果列表页面

//router.js
'use strict';

/**
 * @param {Egg.Application} app - egg application
 */
module.exports = app => {
  const {
    router,
    controller
  } = app;
  router.get('/', controller.home.index); //默认页
  router.resources('fruits', '/fruits', controller.fruits)
};
//fruits.js
'use strict'; //严格模式

const Controller = require('egg').Controller; //Controller类
let fruitList = ["香蕉", "苹果", "西瓜"]
class FruitsController extends Controller {

  //index方法  用于获取query的get请求参数
  async index() {
    this.ctx.body = fruitList
  }

  //createPage方法  用于表单提交页面
  async new() {
    this.ctx.body = `
    
`
} //插入提交的水果 async create() { let fruit = this.ctx.request.body fruitList.push(fruit.fruitName) //跳转到/fruits get请求 this.ctx.redirect('/fruits') } } module.exports = FruitsController

你可能感兴趣的:(javascript,开发语言,ecmascript)