Koa入门2 koa-router 封装 组合 中间件

接着 Koa入门继续 传送门— Koa入门

我们监听的是3000端口 但是路径没有限制,所以输入以下路径都是OK的
http://localhost:3000/****
Koa入门2 koa-router 封装 组合 中间件_第1张图片
这样的话怎么处理 ?
按理说 我们想要每个路由对应不同的页面渲染
实现如下

// 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:
const Koa = require('koa');

// 创建一个Koa对象表示web app本身:
const app = new Koa();

app.use(async (ctx, next) => {
     
  const url = ctx.url;
  ctx.response.type = 'text/html';
  switch (url){
     
    case '/':
      ctx.response.body = '

Hello, koa2!

'
; break; case '/haha': ctx.response.body = '

haha!

'
; break; case '/xixi': ctx.response.body = '

xixi!

'
; break; } await next(); // 调用下一个middleware }); // 在端口3000监听: app.listen(3000); console.log('app started at port 3000...');

Koa入门2 koa-router 封装 组合 中间件_第2张图片
这样处理感觉会很笨重 所以我们还是需要做下集中处理的 当当当 koa-router 出现了
首先 安装依赖

npm install koa-router

package.json

{
     
  "scripts": {
     
    "start": "node app.js"
  },
  "dependencies": {
     
    "koa": "^2.12.1",
    "koa-router": "^9.0.1"
  }
}
// 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:
const Koa = require('koa');

// 创建一个Koa对象表示web app本身:
const app = new Koa();
// 注意require('koa-router')返回的是函数:

const route = require('koa-router');
const router = route()

app.use(async (ctx, next) => {
     
  console.log(`Process ${
       ctx.request.method} ${
       ctx.request.url}...`);
  await next();
});

// add url-route:
router.get('/', async (ctx, next) => {
     
  ctx.response.body = '

Index

'
; }); router.get('/:name', async (ctx, next) => { var name = ctx.params.name; ctx.response.body = `

Hello, ${ name}!

`
; }); // add router middleware: app.use(router.routes()); // 在端口3000监听: app.listen(3000); console.log('app started at port 3000...');

Koa入门2 koa-router 封装 组合 中间件_第3张图片
Koa入门2 koa-router 封装 组合 中间件_第4张图片
这里 我们根据 get请求 可以在请求路径中使用带变量的/hello/:name 变量可以通过ctx.params.name访问
但是post 请求 是表单或者json的形式 它作为request的body发送,我们需要一个middleware来解析原始request请求,然后,把解析后的参数,绑定到ctx.request.body中 于是引入koa-bodyparser

// 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:
const Koa = require('koa');

// 创建一个Koa对象表示web app本身:
const app = new Koa();
// 注意require('koa-router')返回的是函数:

const route = require('koa-router');
const router = route()

const bodyParser = require('koa-bodyparser');
const use_bodyParser = bodyParser();


router.get('/', async (ctx, next) => {
     
  ctx.response.body = `

Index

Name:

Password:

`
; }); router.post('/signin', async (ctx, next) => { let name = ctx.request.body.name || '', password = ctx.request.body.password || ''; console.log(`signin with name: ${ name}, password: ${ password}`); if (name === 'admin' && password === '12345') { ctx.response.body = `

Welcome, ${ name}!

`
; } else { ctx.response.body = `

Login failed!

Try again

`
; } }); app.use(use_bodyParser); // 需要注册在koa-router之前 // add router middleware: app.use(router.routes()); // 在端口3000监听: app.listen(3000); console.log('app started at port 3000...');

Koa入门2 koa-router 封装 组合 中间件_第5张图片
Koa入门2 koa-router 封装 组合 中间件_第6张图片

由于都写在app.js里面 代码冗余太多 所以我们优化下
新增containers文件夹 里面控制跳转路径以及其对应的逻辑处理
Koa入门2 koa-router 封装 组合 中间件_第7张图片
login.js

let fn_index = async (ctx, next) => {
     
  ctx.response.body = `

Index

Name:

Password:

`
; }; let fn_signin = async (ctx, next) => { let name = ctx.request.body.name || '', password = ctx.request.body.password || ''; console.log(`signin with name: ${ name}, password: ${ password}`); if (name === 'koa' && password === '12345') { ctx.response.body = `

Welcome, ${ name}!

`
; } else { ctx.response.body = `

Login failed!

Try again

`
; } }; module.exports = { 'GET/': fn_index, 'POST/signin': fn_signin };

hello.js

var fn_hello = async (ctx, next) => {
     
  var name = ctx.params.name;
  ctx.response.body = `

Hello, ${ name}!

`
; }; module.exports = { 'GET/hello/:name': fn_hello };

app.js

// 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:
const Koa = require('koa');

// 创建一个Koa对象表示web app本身:
const app = new Koa();
// 注意require('koa-router')返回的是函数:

const route = require('koa-router');
const router = route()

const bodyParser = require('koa-bodyparser');
const use_bodyParser = bodyParser();

const fs = require('fs')


function addControllers(router) {
     
  // 先导入fs模块,然后用readdirSync列出文件
  // 这里可以用sync是因为启动时只运行一次,不存在性能问题:
  const files = fs.readdirSync(__dirname + '/controllers');
  // 过滤出.js文件:
  const js_files = files.filter((f) => {
     
    return f.endsWith('.js');
  });
  for (let f of js_files){
      // 可跳出循环
    console.log('遍历对的controller为,', f);
    const mapping = require(`${
       __dirname}/controllers/${
       f}`);
    console.log('mapping', mapping)
    findMapping(router,mapping)
  }
}

function findMapping(router,mapping){
     
  for (let url in mapping) {
      // 遍历对象
    console.log('拿到的url', url)
    if (url.startsWith('GET')) {
     
      const path = url.substring(3); // 取 跳转路径 / 或者 /hello/:name
      console.log('那到的path', path);
      router.get(path, mapping[url]);
    } else if (url.startsWith('POST')) {
     
      const path = url.substring(4); // 取 跳转路径/signin
      router.post(path, mapping[url]);
    }
  } 
}

// 调用方法
addControllers(router);

app.use(use_bodyParser); // 需要注册在koa-router之前
// add router middleware:
app.use(router.routes());


// 在端口3000监听:
app.listen(3000);
console.log('app started at port 3000...');



执行

npm run start

Koa入门2 koa-router 封装 组合 中间件_第8张图片

Koa入门2 koa-router 封装 组合 中间件_第9张图片

Koa入门2 koa-router 封装 组合 中间件_第10张图片
改变路径
Koa入门2 koa-router 封装 组合 中间件_第11张图片

这样还是都写在了app.js里面
怎样才能抽出呢 只在app里面调用即可 这就涉及都了封装中间件,我理解 中间件就是一个封装的独立的逻辑的函数

项目架构
Koa入门2 koa-router 封装 组合 中间件_第12张图片

所以在controllers文件夹下再设置一个contol.js 作为中间件 导出函数
control.js

const fs = require('fs')


function addControllers(router) {
     
  // 先导入fs模块,然后用readdirSync列出文件
  // 这里可以用sync是因为启动时只运行一次,不存在性能问题:
  const files = fs.readdirSync(__dirname) ;
  console.log("file", files)
  // 过滤出.js文件:
  const js_files = files.filter((f) => {
     
    return f.endsWith('.js');
  });
  for (let f of js_files) {
      // 可跳出循环
    console.log('遍历对的controller为,', f);
    const mapping = require(`${
       __dirname}/${
       f}`);
    console.log('mapping', mapping)
    findMapping(router, mapping)
  }
}

function findMapping(router, mapping) {
     
  for (let url in mapping) {
      // 遍历对象
    console.log('拿到的url', url)
    if (url.startsWith('GET')) {
     
      const path = url.substring(3); // 取 跳转路径 / 或者 /hello/:name
      console.log('那到的path', path);
      router.get(path, mapping[url]);
    } else if (url.startsWith('POST')) {
     
      const path = url.substring(4); // 取 跳转路径/signin
      router.post(path, mapping[url]);
    }
  }
}

module.exports = function(){
     
  console.log('haha')
  const  // 如果不传参数 ,默认为controllers目录
        route = require('koa-router');// 注意require('koa-router')返回的是函数:
        router = route();
  // 调用方法
  addControllers(router);
  return router.routes(); // 必须return出去
}


app.js

// 导入controller middleware:
// 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:
const Koa = require('koa');

// 创建一个Koa对象表示web app本身:
const app = new Koa();

const bodyParser = require('koa-bodyparser');
const use_bodyParser = bodyParser();

const controller = require('./controllers/control');
console.log(typeof controller)
app.use(use_bodyParser); // 需要注册在koa-router之前
// add router middleware:
app.use(controller()); // 调用return 出来的函数


// 在端口3000监听:
app.listen(3000);
console.log('app started at port 3000...');


启动

npm run start

Koa入门2 koa-router 封装 组合 中间件_第13张图片

Koa入门2 koa-router 封装 组合 中间件_第14张图片

你可能感兴趣的:(Node.js)