客户管理系统开发定制koa框架

文章目录


koa是由Express客户管理系统开发定制原班人马打造的,客户管理系统开发定制致力于成为一个更小、客户管理系统开发定制更富有表现力、更健壮的Web框架。使用koa编写web应用,客户管理系统开发定制通过组合不同的generator,客户管理系统开发定制可以免除重复繁琐的客户管理系统开发定制回调函数嵌套 ,客户管理系统开发定制并极大地提升错误处理的效率。koa客户管理系统开发定制不在内核方法中绑定任何中间件,客户管理系统开发定制它仅仅提供了-客户管理系统开发定制个轻量优雅的函数库,使得编写Web应用变得得心应手。

koa和的区别

  • Koa采用洋葱模型
    通常都会说Koa是洋葱模型,这重点在于中间件的设计。但是按照上面的分析,会发现Express也是类似的,不同的是Express中间件机制使用了Callback 实现,这样如果出现异步则可能会使你在执行顺序上感到困惑,因此如果我们想做接口耗时统计、错误处理Koa的这种中间件模式处理起来更方便些。最后一点响应机制也很重要,
    Koa不是立即响应,是整个中间件处理完成在最外层进行了响应,而Express则是立即响应。

  • Koa更轻量
    koa不提供内置的中间件;
    koa不提供路由,而是把路由这个库分离出来了(koa/router)

  • Context对象
    koa增加了一个Context的对象,作为这次请求的上下文对象(在koa2中作为中间件的第一个参数传入)。同时Context上也挂载了Request和Response两个对象。Express类似, 这两个对象都提供了大量的便捷方法辅助开发这样的话对于在保存一些公有的参 数的话变得更加合情合理。

  • 异步流程控制
    express采用callback来处理异步,koa采用async/await。
    async/await使用同步的写法来处理异步,明显好于callback和promise,

  • 中间件模型
    express基于connect中间件,线性模型;
    koa中间件采用洋葱模型(对于每个中间件,在完成了-些事情后,可以非常优雅的将控制权传递给下一个中间件,并能够等待它完成,当后续的中间件完成处理后,控制权又回到了自己)


代码示例:

同步代码

同步方法没有什么区别:

  • 01-express-同步.js
const express = require("express")const app = express()app.use((req, res, next) => {    console.log("111111")    next()    console.log("333333")    res.send("hello world")})app.use((req, res, next) => {    // 同步操作    console.log("22222")})app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

运行输出

11111122222333333
  • 1
  • 2
  • 3
  • 01-koa-同步 .js
const Koa = require("koa")const app = new Koa()app.use((ctx, next) => {    console.log("111111")    next()    console.log("333333")    ctx.body("hello world")})app.use((ctx, next) => {    // 同步操作    console.log("22222")})app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

运行输出:

11111122222333333
  • 1
  • 2
  • 3

异步代码

next()表示可以执行下一个中间件,当下一个中间件执行完成之后,如果上一个中间件没有执行完,再返回上一个中间件继续执行。

01-express-异步.js

const express = require("express")const app = express()app.use(async (req, res, next) => {    console.log("111111")    await next()    console.log("444444")    res.send("hello world")})app.use(async (req, res, next) => {    console.log("22222")     // 异步操作    await delay(1000)    console.log("33333")})function delay(time) {    return new Promise((resolve, reject) => {        setTimeout(resolve,time)    })}app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

运行输出:

1111112222244444433333
  • 1
  • 2
  • 3
  • 4

由于next()返回的不是promise对象因此await不起作用,所以输出不会像我们所想输出

  • 01-koa-异步.js
const Koa = require("koa")const app = new Koa()app.use((ctx, next) => {    console.log("111111")    next()    console.log("444444")})app.use((ctx, next) => {    console.log("22222")    // 异步操作    delay(1000)    console.log("33333")})function delay(time) {    return new Promise((resolve, reject) => {        setTimeout(resolve,time)    })}app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

运行输出:

1111112222233333444444
  • 1
  • 2
  • 3
  • 4

koa洋葱模型,正常执行。

koa下载安装

  • npm init
  • npm i koa
  • Koa基本框架
const Koa = require("koa")const app = new Koa()// ctx=context 相当于res和req的合并app.use((ctx, next) => {    })app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

koa的基本使用

  • ctx
    ctx.req//node原生的request对象
    ctx.res//node原生的response对象
    cts.request//koa封装好的的request对象
    cts.response//koa封装好的的response对象
  • 向返回数据到前端页面
    ctx.response.body = 返回的内容
       // 返回代码片段    ctx.response.body = "<b>hello world</b>"    // 返回json数据    ctx.response.body = { name: "yang", age: 18 }
  • 1
  • 2
  • 3
  • 4

但是后面返回的会覆盖前面返回的

  • 获取请求路径
    ctx.request.path
 console.log(ctx.request.path)
  • 1
  • 注: ctx.request.path可以简写成 ctx.path
    ctx的多数方法都可以省去request 和 response。

koa的路由

koa中没有路由,需要下载另一个模块

  • 下载:npm i koa-router
  • 使用:
const Koa = require("koa")const Router = require("koa-router")const app = new Koa()const router = new Router()router.get("/list",(ctx, next) => {   ctx.body = ["111","222","333"]})// 注册路由app.use(router.routes())// 当请求方法错误时(比如需要get请求发成了post请求),提示相应错误app.use(router.allowedMethods())app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 路由实现增删改查
const Koa = require("koa")const Router = require("koa-router")const app = new Koa()const router = new Router()router.post("/list",(ctx, next) => {    ctx.body = {        ok: 1,        info:"add list success"   }})router.get("/list",(ctx, next) => {   ctx.body = ["111","222","333"]})router.put("/list/:id", (ctx, next) => {    console.log(ctx.params)    ctx.body = {        ok: 1,        info:"put list success"    }})router.del("/list/:id", (ctx, next) => {    ctx.body = {        ok: 1,        info:"del list success"    }})// 注册路由app.use(router.routes())// 当请求方法错误时(比如需要get请求发成了post请求),提示相应错误app.use(router.allowedMethods())app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 路由文件拆分,紫萼在一根文件中太乱了,不同的请求应该放在不同的路由文件中,然后进行引入。

    index.js:
const Koa = require("koa")const Router = require("koa-router")const app = new Koa()const router = new Router()const userRouter = require("./routes/user")const listRouter = require("./routes/list")// 先注册路由级组件router.use("/user", userRouter.routes(),userRouter.allowedMethods())router.use("/list",listRouter.routes(),listRouter.allowedMethods())// 再注册应用级组件app.use(router.routes())// 当请求方法错误时(比如需要get请求发成了post请求),提示相应错误app.use(router.allowedMethods())app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

user.js

const Router = require("koa-router")const router = new Router()router.post("/",(ctx, next) => {    ctx.body = {        ok: 1,        info:"add user success"   }})router.get("/",(ctx, next) => {   ctx.body = ["111","222","333"]})router.put("/:id", (ctx, next) => {    console.log(ctx.params)    ctx.body = {        ok: 1,        info:"put user success"    }})router.del("/:id", (ctx, next) => {    ctx.body = {        ok: 1,        info:"del user success"    }})module.exports = router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

list.js

const Router = require("koa-router")const router = new Router()router.post("/",(ctx, next) => {    ctx.body = {        ok: 1,        info:"add list success"   }})router.get("/",(ctx, next) => {   ctx.body = ["111","222","333"]})router.put("/:id", (ctx, next) => {    console.log(ctx.params)    ctx.body = {        ok: 1,        info:"put list success"    }})router.del("/:id", (ctx, next) => {    ctx.body = {        ok: 1,        info:"del list success"    }})module.exports = router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 也可以将 index.js中的 注册路由级组件 提出来
    user.js和list.js不用修改,再router下新建index.js


index.js

const Koa = require("koa")const app = new Koa()const router = require("./routes")// 再注册应用级中间件app.use(router.routes())// 当请求方法错误时(比如需要get请求发成了post请求),提示相应错误app.use(router.allowedMethods())app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

router/index.js:

const Router = require("koa-router")const router = new Router()const userRouter = require("./user")const listRouter = require("./list")// 统一加前缀router.prefix("/api")// 先注册路由级中间件router.use("/user", userRouter.routes(),userRouter.allowedMethods())router.use("/list", listRouter.routes(), listRouter.allowedMethods())module.exports = router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • router统一加前缀
// 统一加前缀router.prefix("/api")
  • 1
  • 2
  • 路由的重定向
router.use("/home", homeRouter.routes(), homeRouter.allowedMethods())router.redirect("/","/home")//重定向
  • 1
  • 2

表示当访问更目录时会自动成定向到/home.

koa静态资源

  • 安装模块: npm i koa-static
  • 引入模块,配置静态资源:
    index.js:
const Koa = require("koa")const app = new Koa()const static = require("koa-static")const path= require("path")// 先注册路由级中间件const router = require("./routes")// 再注册应用级中间件app.use(router.routes())app.use(static(path.join(__dirname,"public")))// 当请求方法错误时(比如需要get请求发成了post请求),提示相应错误app.use(router.allowedMethods())app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 例子:

    center.html:
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title>    <!-- href="css/center.css" 路径前面不要加前缀路径,因为在index.js中配置好了,静态资源会自动去public文件夹下寻找-->    <link rel="stylesheet" href="/css/center.css"/></head><body>    <div>        center    </div></body></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

center.css

div{    background-color: brown;}
  • 1
  • 2
  • 3

运行访问:http://localhost:3000/center.html

koa获取请求参数

get请求参数获取

在koa中,获取GET请求数据源头是koa中request对象中的query方法或querystring方法。
query返回是 格式化好的参数对象,
querystring返回的是请求字符串,
由于ctx对request的API有 直接引用的方式,所以获取GET请求数据有两个途径:

  • 从上下文中直接获取:
    请求对象ctx.query,返回如{ a:1, b:2 }
    请求字符串ctx.querystring,返回如a=1&b=2
  • 是从上下文的request对象中获取:
    请求对象ctx.request.query,返回如{ a:1, b:2 }
    请求字符串ctx.request.querystring,返回如a=1&b=2

post请求参数获取

对于POST请求的处理,koa-bodyparser中间件可以把koa上下文的formData数据解析到ctx.request.body

  • 配置注册模块
const bodyParser = require('koa-bodyparser')//使用ctx.body解析中间件app.use(bodyParser())
  • 1
  • 2
  • 3
  • 获取
    ctx.request.body(不能简写)

输出:eg:

{ username: 'bbb', password: '123456' }
  • 1

koa的ejs模板

  • 需要安装两个模块
    npm install --save koa-views
    npm install --save ejs
  • 模板配置
const views = require("koa-views")// 配置模板引擎,将ejs模板文件放在views文件夹下app.use(views(path.join(__dirname,"views"),{extension:"ejs"}))
  • 1
  • 2
  • 3
  • 模板使用
    /home请求
const Router = require("koa-router")const router = new Router()router.get("/", async (ctx, next) => {    // 是异步的,需要等待模板解析完成之后再返回页面    await ctx.render("home",{username:"yang"})// 自动去views下找home.ejs(入口index.js中配置了)})module.exports = router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

home.ejs

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title></head><body>    <h1>Home</h1>    <h2>欢迎<%=username%>回来</h2></body></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

输出:

koa- 登录鉴权

cookie和session

koa-cookie

koa提供了从上下文直接读取、写入cookie的方法

  • ctx.cookies.get(name, [options])读取上下文请求(前端)中的cookie
  • ctx.cookies.set(name, value, [options])在上下文中写入cookie

koa-session

  • 需要下载模块koa-session-minimal
    npm i koa-session-minimal
  • 模块配置
    index.js:
    拦截
const Koa = require("koa")const app = new Koa()const static = require("koa-static")const path = require("path")const bodyParser = require('koa-bodyparser')const views = require("koa-views")const session = require("koa-session-minimal")// 先注册路由级中间件const router = require("./routes")//使用ctx.body解析中间件,获取post参数app.use(bodyParser())// 配置静态资源app.use(static(path.join(__dirname,"public")))// 配置模板引擎app.use(views(path.join(__dirname, "views"), { extension: "ejs" }))// session配置app.use(session({    // 设置钥匙    key: "yangsessionId",    cookie:{        maxAge:1000*60    }}))// session判断拦截app.use(async (ctx, next) => {    if (ctx.url.includes("login")) {        await next()        return     }    if (ctx.session.user) {        ctx.session.date = Date.now()        await next()    }else{        ctx.redirect("/login")    }})// 再注册应用级中间件app.use(router.routes())app.use(router.allowedMethods())app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

登陆时设置session

router.post("/login", (ctx) => {    console.log(ctx.request.body)    const { username, password } = ctx.request.body    if (username === 'yang' && password === "123456") {        // 登陆成功设置session,给session赋值        ctx.session.user = {            username:"yang"        }        ctx.body = {            ok: 1,        }    } else {        ctx.body = {            ok: 0,        }    }    })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

JWT

  • JWT模块
    util/JWT.js:
var jwt = require("jsonwebtoken")const secret ='yang-secret'const JWT = {    // 加密    generate(value,expires) {        return jwt.sign(value,secret,{expiresIn:expires})    },    // 解密    verify(token) {        try {            return jwt.verify(token, secret)        } catch (error) {            return false        }    }}module.exports = JWT
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 登陆成功设置token
router.post("/login", (ctx) => {    console.log(ctx.request.body)    const { username, password } = ctx.request.body    if (username === 'yang' && password === "123456") {        // 登陆成功设置token,插入到header中        const token = JWT.generate({            _id: "123456",            username:"yang"        }, "10s")        // 将token返回在header中        ctx.set("Authorization",token)        ctx.body = {            ok: 1,        }    } else {        ctx.body = {            ok: 0,        }    }    })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • login.ejs
    登录成功将token设置在前端页面上:(axios拦截器)
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title>    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>    <script type='text/javascript'>        // 拦截器        // 请求发出前执行的方法      axios.interceptors.request.use(function (config) {          console.log("请求发出前执行的方法")          return config;        }, function (error) {                   return Promise.reject(error);      });        // 请求成功之后第一个调用的方法      axios.interceptors.response.use(function (response) {            console.log("请求成功之后第一个调用的方法")            const {authorization} = response.headers            authorization && localStorage.setItem("token",authorization)            return response;          }, function (error) {                        return Promise.reject(error);      });    </script></head><body>    <h1>登录界面</h1>    <div>        <div>用户名:<input id="username" /></div>        <div>密码:<input type="password" id="password" /></div>        <div><button id="login">登录</button></div>    </div>    <script type='text/javascript'>        var login = document.querySelector("#login");        var username = document.querySelector("#username");        var password = document.querySelector("#password");        login.onclick = () => {          axios.post("/user/login",{            username: username.value,            password: password.value          }).then(res=>{            if(res.data.ok==1){              console.log(res.data)              // 存储token(拉杰其直接进行了存储)              location.href="/"            }else{                console.log(res)                alert("用户名密码错误")            }          })      };    </script></body></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • index.js

响应请求之前先判断token是否过期

const Koa = require("koa")const app = new Koa()const static = require("koa-static")const path = require("path")const bodyParser = require('koa-bodyparser')const views = require("koa-views")const session = require("koa-session-minimal")const JWT = require("./utils/jwt")// 先注册路由级中间件const router = require("./routes")//使用ctx.body解析中间件,获取post参数app.use(bodyParser())// 配置静态资源app.use(static(path.join(__dirname,"public")))// 配置模板引擎app.use(views(path.join(__dirname, "views"), { extension: "ejs" }))// token判断拦截app.use(async (ctx, next) => {    if (ctx.url.includes("login")) {        await next()        return    }    const token = ctx.headers["authorization"]?.split(" ")[1]    if (token) {        const payload = JWT.verify(token)        if (payload) {            // 重新计算token的过期时间            const newToken = JWT.generate({                _id: payload._id,                username: payload.username            }, "1d")            // 将token返回在header中            ctx.set("Authorization",token)                        await next()        } else {            ctx.status = 401,            ctx.body = {errCode:-1,errInfo:"token过期"}        }    } else {        await next()    }})// 再注册应用级中间件app.use(router.routes())app.use(router.allowedMethods())app.listen(3000)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • home.ejs:
<!DOCTYPE html><html>  <head>    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>    <script type='text/javascript'>        // 拦截器        // 请求发出前执行的方法      axios.interceptors.request.use(function (config) {          console.log("请求发出前执行的方法")          // 将token给后端          const token = localStorage.getItem("token")          // config是请求对象,可以传递给后端,Bearer 是规范          config.headers.Authorization = `Bearer ${token}`          return config;        }, function (error) {                   return Promise.reject(error);      });        // 请求成功之后第一个调用的方法      axios.interceptors.response.use(function (response) {            console.log("请求成功之后第一个调用的方法")            const {authorization} = response.headers            authorization && localStorage.setItem("token",authorization)            return response;            if(response.data.ok==0){              location.href="/login"            }          }, function (error) {            console.log("请求成功之后第一个调用的方法err")            console.log(error.response.status)            if(error.response.status===401){              localStorage.removeItem("token")              location.href="/login"            }            return Promise.reject(error);      });      </script>      <style>        td img{          width: 80px;          height: 80px;        }      </style>  </head>  <body>    <div>      <h1>后台管理系统        <button id="exit">退出登录</button>        </h1>      <br />      <table border="1">        <thead>          <tr>            <td>id</td>            <td>用户</td>            <td>年龄</td>          </tr>        </thead>        <tbody></tbody>      </table>    </div>    <script type="text/javascript">      var exit = document.querySelector("#exit");      axios.get("/home/list").then((res) => {           res = res.data            console.log(res);            var tbody = document.querySelector("tbody");            // map映射            tbody.innerHTML = res              .map(                (item) => `              <tr>                <td>${item._id}</td>                <td>${item.username}</td>                <td>${item.age}</td>              </tr>              `              )              .join("");        })      exit.onclick = ()=>{        // 直接移除前端的token       localStorage.removeItem("token")         location.href="/login"           }    </script>  </body></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

koa 文件上传

  • 安装 multer 和@koa/multer
    npm install --save @koa/multer multer
    用法和Express的multer一样。

  • 模块配置

const multer = require("@koa/multer")// 文件存储地址const upload = multer({dest:"public/uploads"})// upload.single("avatar"):接收文件router.post("/upload", upload.single("avatar"),(ctx) => {    console.log(ctx.request.body,ctx.file)    ctx.body={ok:1}})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

koa 操作MongoDB

  • 下载模块:npm i mongoose
  • 启动MongoDB
  • 在vscode中配置mongoDB

    db.config.js:
// 连接数据库const mongoose = require("mongoose")mongoose.connect("mongodb://127.0.0.1:27017/yang_project")// 插入集合和数据,yang_project会自动创建
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • index.js引入
// 链接数据库require("./config/db.config")
  • 1
  • 2
  • 向数据库中存数据
// upload.single("avatar"):接收文件router.post("/upload", upload.single("avatar"),async (ctx) => {    console.log(ctx.request.body, ctx.file)        const { username, password, age } = ctx.request.body    const avatar = ctx.file ? `/uploads/${ctx.file.filename}` : `/uploads/9f774d77e9072c2912efb7528249db42`        // 利用UserModel模型进行存储操作 UserModel.create    await UserModel.create({        username,        age,        password,        avatar    })    ctx.body={ok:1}})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

代码获取:
链接:
提取码:xtfx

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发