新一代node.js web开发框架Koa入门学习笔记

原创
小哥 3年前 (2022-10-27) 阅读数 9 #CSS教程
文章标签 CSS

目录

Koa

新一代 node.js web 开发框架。

构建一台服务器

node 初始化 package.json

npm init -y

参数:
-y 使用所有选项的默认设置,不要一步步确认。

{
  "name": "RyeKoa",
  "version": "1.0.0",
  "description": "Koa 零基本入门学习笔记",
  "main": "app.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "觀·自在",
  "license": "ISC"
}

安装 Koa 模块

cnpm install koa --save 简写 npm i koa -S

参数:
--save 将在 package.json 将安装包的版本信息添加到

// package.json
{
  "name": "RyeKoa",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "koa": "^2.13.1"
  }
}

创建应用程序条目文件 app.js

最简实现

// app.js
const Koa = require(koa)

const app = new Koa()

app.use(async (ctx, next) => {
    ctx.response.body = Hello Koa!
})

app.listen(3000)

这是实现的最简单版本。

Koa 应用程序是一个集合 中间件 函数的对象,以类似堆栈的方式组织和执行。
app.use() 函数用于对中间件进行注册。
ctx 是 Koa 上下文
next 是中间件必须的,调用 next() 用于执行下一个中间件,这里不使用它,因为 ctx.response.body 默认呼叫 next()

上述代码中使用的中间件也可以缩写为以下形式:

app.use(async ctx => {
    // 这是 Response 别名
    ctx.body = Hello Koa!
})

上下文

Koa Context 将 node 的 requestresponse 对象被封装到单个对象中以供写入。 Web 应用程序和 API 提供了许多有用的方法。 这些操作在 HTTP 在服务器开发中经常使用它们,它们被添加到这一级别,而不是更高级别的框架,这迫使中间件重新实现这一通用功能。

每个 请求将创建一个 Context并作为中间件中的接收方引用,或者。 ctx 标识符,如以下代码片断所示:

app.use(async ctx => {
  ctx; // 这是 Context
  ctx.request; // 这是 koa Request
  ctx.response; // 这是 koa Response
});

为方便起见,许多上下文的访问器和方法被直接委托给它们。 ctx.requestctx.response 除此之外,它们都是一样的。 例如 ctx.bodyctx.typectx.length 委托给 response 对象,ctx.path 和 ctx.method 委托给 request。

Request 别名

以下访问器和 Request 别名等效项:

  • ctx.header
  • ctx.headers
  • ctx.method
  • ctx.method=
  • ctx.url
  • ctx.url=
  • ctx.originalUrl
  • ctx.origin
  • ctx.href
  • ctx.path
  • ctx.path=
  • ctx.query
  • ctx.query=
  • ctx.querystring
  • ctx.querystring=
  • ctx.host
  • ctx.hostname
  • ctx.fresh
  • ctx.stale
  • ctx.socket
  • ctx.protocol
  • ctx.secure
  • ctx.ip
  • ctx.ips
  • ctx.subdomains
  • ctx.is()
  • ctx.accepts()
  • ctx.acceptsEncodings()
  • ctx.acceptsCharsets()
  • ctx.acceptsLanguages()
  • ctx.get()

Response 别名

以下访问器和 Response 别名等效项:

  • ctx.body
  • ctx.body=
  • ctx.status
  • ctx.status=
  • ctx.message
  • ctx.message=
  • ctx.length=
  • ctx.length
  • ctx.type=
  • ctx.type
  • ctx.headerSent
  • ctx.redirect()
  • ctx.attachment()
  • ctx.set()
  • ctx.append()
  • ctx.remove()
  • ctx.lastModified=
  • ctx.etag=

启动服务器

node app

因此,使用 node 命令启动服务器并访问本地地址端口。 3000

浏览器访问地址:
http://127.0.0.1:3000/
http://localhost:3000/

此时,浏览器会响应:

自动服务器重新部署

Node.js 发展援助 nodemon

修改代码后,每次都需要停机重启。 Koa 应用程序时,所做的更改将生效。
使用了 nodemon 之后,它将监视项目中的所有文件,并在发现任何更改后自动重新启动应用程序。

安装 nodemon
npm i nodemon -g
参数
i 即 install
-g 全局安装(我们都执行通用命令行使用的工具的全局安装)

启动应用程序:
nodemon app

这样,当您修改代码时:

...
app.listen(3000, () => {
    console.log("服务器已启动,http://localhost:3000");
})
...

在控制台中,您将看到。 nodemon 自动为您重新启动服务器:

$ nodemon app
[nodemon] 2.0.7
[nodemon] to restart at any time, enter rs
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting node app.js
[nodemon] restarting due to changes...
[nodemon] starting node app.js
服务器已启动,http://localhost:3000

中间件

Koa 应用程序是一个集合 中间件 函数的对象,以类似堆栈的方式组织和执行。
使用 app.use() 函数用于对中间件进行注册。
ctx 是上下文
next 是中间件必须的,调用 next() 用来执行下一个中间件,如果没有,程序就会挂在这里。

const Koa = require(koa)
const app = new Koa()

app.use(async (ctx, next) => {
    ctx.name = Koa
    next()
})
app.use(async ctx => {
    ctx.body = Hello, ${ctx.name}!
})

app.listen(3000, () => {
    console.log("服务器已启动,http://localhost:3000");
})

洋葱模型

Koa 新一代 node.js web 开发框架。它最大的特点是其独特的中间件流程控制,这是一个典型的洋葱模型。

下面两个图清楚地显示了中间件最终如何生成请求。在这种模式下,中间件的开发和使用非常方便。

const Koa = require(koa)

const app = new Koa()

app.use(async (ctx, next) => {
    console.log(中间件1:开始);
    ctx.name = Koa
    await next()
    console.log(中间件1:结束);

})

app.use(async ctx => {
    console.log(中间件2:开始);
    ctx.body = Hello, ${ctx.name}!
    console.log(中间件2:结束);
})

app.listen(3000, () => {
    console.log("服务器已启动,http://localhost:3000");
})

控制台输出:

怎么了,有没有一点感觉。当程序运行时 await next() 当当前程序挂起时,它将进入下一个中间件,并且不会回去继续处理,直到它完成。

Koa 中间件的实现重点

  • 上下文 ctx 保存和交付
  • 中间件的顺序管理
  • next 的使用( 注意 next() 前边的 await

定制中间件

定制一个中间件一点也不难。
步骤1:定义方法

function MidTest(ctx) {
    global.console.log(执行了定制中间件...)
}

第二部分:导出此方法

  1. 公开函数
  2. 此函数返回一个参数 ctx 与 next 的 回调函数
  3. 执行我们希望在回调函数中完成的方法。

    module.exports = function () { return async function (ctx, next) { MidTest(ctx); // todo await next(); //运行后,将其移交给下一个中间件。 // todo } }

完整的中间件定义:

// ./middleware/mid-test.js
function MidTest(ctx) {
    global.console.log(执行了定制中间件...)
}
module.exports = function () {
    return async function (ctx, next) {
        MidTest(ctx);
        await next(); //运行后,将其移交给下一个中间件。
    }
}

使用定制中间件:
第一步:引入中间件

const
    MidTest = require(./middleware/mid-test)

第二部分:注册中间件

app.use(MidTest())

运行应用程序,将看到定制中间件的执行结果:

Koa 路由

安装路由中间件 koa-router

cnpm i koa-router -S

使用 koa-router

导入路由模块:

const Router = require(koa-router)

实例化的路由(支持传递参数):

const router = new Router()

配置路由:

router.get(/, async (ctx, next) => {
    ctx.body = Hello, Koa Router!
})

注册路由中间件:
路由实例 router,单独呼叫 router.routes() 和 router.allowedMethods() 得到两个中间件。然后使用 app.use() 注册这两个中间件。

  • 调用router.routes()组装匹配的路由并返回合并的中间件。
  • 调用router.allowedMethods()获取在发送不符合要求的请求时返回的中间件。 405 Method Not Allowed501 Not Implemented

    app.use(router.routes()) app.use(router.allowedMethods({ // throw: true, // 引发错误,而不是设置响应头状态 // notImplemented: () => 不支持当前请求所需的功能, // methodNotAllowed: () => 不支持的请求方法 }))

完整的示例代码:

// app.js
const
    Koa = require(koa),
    Router = require(koa-router)

const
    app = new Koa(),
    router = new Router()

router.get(/, async (ctx, next) => {
    ctx.body = Hello, Koa Router!
})

app.use(router.routes())

app.listen(3000, () => {
    console.log("服务器已启动,http://localhost:3000");
})

处理请求

koa-router 提供了 .get、.post、.put 和 .del 方法来处理各种请求,但在实践中, 我们大多数人只会接触到 POST 和 GET ,因此下面的描述仅针对这两种请求类型。

get:用于接收GET请求

router.get(/, async (ctx, next) => {
    ctx.body = Hello, Koa Router!
})

post:用于接收POST请求

router.post(/signin, async (ctx, next) => {
    ctx.body = Hello, POST!
})

all:用于接收GET与POST请求

router.all(/, async (ctx, next) => {
    ctx.body = Hello, POST!
})

请求参数

有时,您需要从 URL 获取具体参数主要有两类: params 和 query 。 这两个参数的取值如下:

params 参数:
router.get(/:catalog/:title, async (ctx, next) => {
    ctx.body = Hello, GET! 页面参数 catalog:${ctx.params.catalog} title:${ctx.params.title}
})


query 参数
router.get(/user, async (ctx, next) => {
    console.log(ctx.query)
    ctx.body = Hello, GET! 页面参数 Name:${ctx.query.name} Age:${ctx.query.age}
})

post 参数

路由嵌套

路由前缀

路由分离

使用静态文件

设置静态目录:public并创建一个文件。 hello.html

安装: koa-static 模块

直接访问是不可访问的,这里我们使用中间件。 koa-static 模块
安装 koa-static 模块
npm i koa-static -S

用法:导入、配置、注册

// app.js
...
const KoaStatic = require(koa-static)
app.use(KoaStatic(__dirname + /public))
...

访问静态资源:

模板引擎

安装:koa-views

cnpm i koa-views -S
cnpm i ejs -S

编写模板

在根目录下创建 views 文件夹,位于 views 下创建 tpl_fruit.ejs 档案。代码如下:





    
    
    
    Document
    
    
    
          
	      
	




    

<%=title %>

    <% fruits.forEach((fruit)=>{%>
  • <%=fruit %>
  • <%})%>

使用模板:导入、配置、注册

// app.js
...
const
    path = require(path),
    views = require(koa-views)

// 注册模板引擎
app.use(views(path.join(__dirname, views), {
    map: {
        ejs: ejs
    }
}))

/**
 * 配置路由
 * 使用模板引擎输出
 */
router.get(/favourite, async (ctx, next) => {
    await ctx.render(tpl_fruit.ejs, {
        title: Hello,我最喜欢的水果:,
        fruits: [Apple, Watermelon, Strawberry]
    })
})
...

访问:http://localhost:3000/favourite

有趣的模板后缀

// 注册模板引擎
app.use(views(path.join(__dirname, views), {
    map: {
        love: ejs
    }
}))

/**
 * 配置路由
 * 使用模板引擎输出
 */
router.get(/favourite, async (ctx, next) => {
    await ctx.render(tpl_fruit.love, {
        title: Hello,我最喜欢的水果:,
        fruits: [Apple, Watermelon, Strawberry]
    })
})

这样,当您自定义模板时,您就可以使用它。 .love 带有后缀的文件:

我们还可以同时使用多个模板引擎:

// 注册模板引擎
app.use(views(path.join(__dirname, views), {
    map: {
        love: ejs,
        html: underscore
    }
}))

如果我们只使用一个模板引擎(通常只有一个),那么当我们注册模板引擎时,我们可以用不同的方式编写它:

// 注册模板引擎
app.use(views(path.join(__dirname, views), {
    extension: ejs
}))

这样做的好处是,当我们重新配置路由时,我们不需要指定模板的后缀:

/**
 * 配置路由
 * 使用模板引擎输出
 */
router.get(/favourite, async (ctx, next) => {
    await ctx.render(tpl_fruit, {
        title: Hello,我最喜欢的水果:,
        fruits: [Apple, Watermelon, Strawberry]
    })
})

深入 koa-views

上面的代码被传递 app.use(views(path, args)) 注册视图中间件,它返回一个参数。 ctx 与 next 的 回调函数

小白的理解:中间件是一个有特殊约定的功能,它有上下文。 ctx 和 next 参数。

// 中间件
`async (ctx, next) => {
    ctx.name = Koa
    next()
}`

我们可以直接进入 app.use() 直接在以下位置注册中间件:

// 注册中间件
app.use(async (ctx, next) => {
    ctx.name = Koa
    next()
})

或者定义一个返回中间件的值的函数,然后注册该函数。

app.use(views(path, args))

这是可以理解的 views(path, args) ,我们将继续关注:

回调函数 添加到上下文对象 ctx 添加名为 render 用于呈现视图的函数。

以下为 koa-views 源码:

function viewsMiddleware (path, {
  engineSource = consolidate,
  extension = html,
  options = {},
  map
} = {}) {
  return function views (ctx, next) {
    if (ctx.render) return next()

    ctx.render = function (relPath, locals = {}) {
      return getPaths(path, relPath, extension)
        .then((paths) => {
          // do something ...
        })
    }

    return next()
  }
}

在源代码中,请注意: ctx.render = function (relPath, locals = {}) {} ,这句话是针对上下文的。ctx添加了render方法,这样我们就可以进入。 router.get() 中使用 ctx.render(tpl, {title: 使用模板引擎}) 呈现了页面。

模板引擎 koa-art-template

art-template 中文文档
代码示例:

// package.json
{
  "name": "RyeKoa",
  "version": "1.0.0",
  "description": "学习资源",
  "main": "app.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "Rye",
  "license": "ISC",
  "dependencies": {
    "art-template": "^4.13.2",
    "koa": "^2.13.1",
    "koa-art-template": "^1.1.1",
    "koa-router": "^10.0.0",
    "koa-static": "^5.0.0",
    "koa-views": "^7.0.1"
  }
}

// app.js
const
    Koa = require(koa),
    Router = require(koa-router),
    KoaStatic = require(koa-static),
    views = require(koa-views),
    path = require(path),
    render = require(koa-art-template)

const
    app = new Koa(),
    router = new Router()

/**
 * 对静态资源的访问从根开始, 而不是 public
 * 例如:http://localhost:3000/hello.html
 */
app.use(KoaStatic(path.join(__dirname, public)))

/**
 * 配置模板引擎
 * 在 Koa 实例 app 上注册
 * 以及对于上下文 ctx 添加 render 方法
 */
render(app, {
    root: path.join(__dirname, views),
    extname: .html
})

// 配置路由
router.get(/, async ctx => {
    ctx.render(user, {
        name: dy,
        age: 2
    })
})

// 合并配置的路由并注册路由中间件,以及允许的请求方法。
app.use(router.routes()).use(router.allowedMethods({
    // throw: true, // 引发错误,而不是设置响应头状态
    // notImplemented: () => 不支持当前请求所需的功能,
    // methodNotAllowed: () => 不支持的请求方法
}))

app.listen(3000, () => {
    console.log(服务器已启动,http://localhost:3000);
})






    
    
    
    用户信息
    
    
    
          
	      
	



    

用户信息页面

姓名:{{name}}

年龄:{{age}}

做好“模板继承”和“子模板”

我们通常有一个母版页要求,将是通用的。 js、css 和固定的 head、footer 这样的部分被放入母版页,母版页由具有上述共同特征的其他页面继承,便于统一管理和修改。

Bootstrap 它是世界上最受欢迎的前端框架之一,可以轻松快速地构建响应迅速的移动优先网站。
我们的示例目录如下:

在静态资源文件夹中 public 进入我们需要介绍的内容。 bootstrap 资源文件,该文件要求您安装和 配置 koa-static 模块






    
    
    
    {{block title}}学习资源{{/block}}-三好生
    
    
    
          
	      
	
    
    {{block head}}{{/block}}



    

    
{{block header}}{{/block}}
{{block content}}页面内容{{/block}}

@三好生 {{block footer}}{{/block}}

子模板:


我的博客 | 在线云学习 | AI 学习助手

首页:
{ {extend ./__layout.html}} 继承母版页
{ {include __links.html}} 导入子模板
{ {block title}}{ {title}}{ {/block}} 放入自定义内容


{{extend ./__layout.html}}

{{block title}}{{title}}{{/block}}

{{block head}}

{{/block}}

{{block content}}

Hello, 三好生!

丰富的学习资源有助于成为一名好学生。......

Learn more »

语文

爱语文

开始学习 »

数学

爱数学

开始学习 »

英语

爱英语

开始学习 »


{{/block}} {{block footer}} {{include __links.html}} {{/block}}

最终的效果是:

Koa 跨域设置

使用中间件编写跨域设置:

app.use((ctx, next) => {
    // 设置允许跨域
    ctx.set("Access-Control-Allow-Origin", "*");
    ctx.set("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS");
    // 请求标头设置
    ctx.set(
        "Access-Control-Allow-Headers",
        Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild,x-token,sessionToken,token
    );
    if (ctx.method == "OPTIONS") {
        ctx.body = 200;
    } else {
        next();
    }
})

配置服务器支持断点续传

配置 Koa 静态资源支持断点延续。 Accept-Ranges 和 Content-Range

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除