zoukankan      html  css  js  c++  java
  • 全栈项目|小书架|服务器开发-Koa全局路由实现

    什么是路由

    路由就是具体的访问路径,指向特定的功能模块。一个api接口是由ip(域名)+端口号+路径组成,例如 :https://www.npmjs.com/package/koa-router就是一个路由,指向了koa-routernpm页面。

    为什么需要 koa-router 路由

    当然不需要koa-router也能实现路由功能,通过ctx.request.path去指定路径实现。例子如下:

    const koa = require('koa2')
    const app = new koa()
    
    app.use(async (ctx, next) => {
        if (ctx.request.path === '/') { // 首页
          ctx.response.status = 200
          ctx.response.body = 'index'
        } else if (ctx.request.path === '/list') { // 列表页
          ctx.response.status = 200
          ctx.response.body = 'list'
        } else {
        	ctx.throw(404, 'Not found') // 404
        }
      await next()
    })
    
    app.listen(3000)
    

    参考:Koa 路由

    以上代码只是实现两个接口,就写了不少代码,而写是多层的判断代码,可读性已经很差了,这时候怎么办?

    是不是可以将以上代码抽取出去,通过中间件的方式去实现。

    结果是可以的,koa-router就是这样做的。使用koa-router实现的例子如下:

    1. app.js 入口
    2. urls/home.js home 页面的路由

    app.js 的代码如下

    // 路由模块使用前需要先安装和实例化
    const Router = require('koa-router')
    const router = new Router()
    
    // 首页
    app.use(async (ctx, next) => {
        if (ctx.request.path === '/') {
          ctx.response.status = 200
          ctx.response.body = 'index'
        }
        await next()
    })
    
    // 其他页面通过 router 加载
    let urls = fs.readdirSync(__dirname + '/urls')
    urls.forEach((element) => {
        let module = require(__dirname + '/urls/' + element)
        /*
          urls 下面的每个文件负责一个特定的功能,分开管理
          通过 fs.readdirSync 读取 urls 目录下的所有文件名,挂载到 router 上面
        */
        router.use('/' + element.replace('.js', ''), module.routes(), module.allowedMethods())
    })
    app.use(router.routes())
    

    urls/home.js 的代码如下

    const Router = require('koa-router')
    const home = new Router()
    
    // /home
    home.get('/', async (ctx, next) => {
        ctx.response.status = 200
        ctx.response.body = 'home'
        await next()
    })
    
    // home/list
    home.get('/list', async (ctx, next) => {
        ctx.response.status = 200
        ctx.response.body = 'home-list'
        await next()
    })
    
    module.exports = home
    

    通过以上代码基本已经实现了全局路由的功能了,剩下得就是在urls包下创建对应的文件即可,参考home.js即可。

    但是这里的代码还是不够完美,app.js作为入口文件,这里的代码还是有点多了;而且首页和home的路由是分开来实现的。再而且urls路径是固定的,后续文件夹名称或者位置改变都会出现问题。

    那么如何实现呢?
    这里介绍一种思路:

    1. app.js中的代码抽取出来,让app.js尽量简单
    2. 将首页和其他页面都在全局路由中实现

    优雅的全局路由实现

    通过npm引入require-directory

    require-directory npm包的作用是:

    递归地遍历指定目录,对每个文件进行require()

    这里也是利用了这个包去实现的。具体实现如下:

    1. core目录下创建InitManager.js
    const requireDirectory = require('require-directory')
    const Router = require('koa-router')
    /**
    * 加载全局路由
    */
    static initLoadRouters(app){
       // 加载工作目录下的 app/api 下的路径
       const apiDirectory = `${process.cwd()}/app/api`
       
       // 参数:第一个参数固定参数module
       // 第二个参数要加载的模块的文件路径
       // 第三个参数:每次加载一个参数执行的函数
       requireDirectory(module, apiDirectory, {
           visit: whenLoadModule
       })
       
       function whenLoadModule(obj) {
           if(obj instanceof Router ){
               app.use(obj.routes())
           }
       }
    }
    
    module.exports = InitManager
    

    从上面的实现方式可以看出这里使用了process.cwd()获取路径,而原有的代码中是通过__dirname去获取路径,那么二者有什么区别呢?

    NodeJsprocess.cwd()__dirname的区别
    process.cwd() 是当前执行node命令时候的文件夹地址 ——工作目录,保证了文件在不同的目录下执行时,路径始终不变
    __dirname 是被执行的js 文件的地址 ——文件所在目录

    1. app.js中加载这个方法即可。
    const app = new Koa()
    InitManager.initLoadRouters(app)
    
    1. app/api下创建相应的接口文件即可,如home.js

    咨询请加微信:轻撩即可。
    在这里插入图片描述

  • 相关阅读:
    appium 搭建及实例
    appium运行时每次默认弹出appiumsetting与unlock重装,关闭这两个步骤的方法
    APPIUM
    分析DuxCms之AdminController
    分析DuxCms之AdminUserModel
    THINKPHP 调试------输出sql语句
    html 标签内联元素和块元素分类【转】
    thinkphp实现数据分页
    thinkphp框架实现删除上传的文件
    初入thinkphp
  • 原文地址:https://www.cnblogs.com/gdragon/p/11802511.html
Copyright © 2011-2022 走看看