美文网首页
一文彻底搞懂koa2和ejs

一文彻底搞懂koa2和ejs

作者: 硅谷干货 | 来源:发表于2023-08-21 18:41 被阅读0次

    一、安装

    开发koa2之前,要求nodejs版本要高于v7.6。因为nodejs7.6版本开始完全支持async/await,所以才能完全支持koa2

    安装语法 : npm install koa --save-dev
    使用之前,先npm init 初始化
    

    二、简单使用

    var koa= require( ‘koa’);
    var app= new koa();
    //中间件,express中的req,res参数变成了ctx
    app.use(async(ctx)=>{    
       ctx.body=”你好koa2.x”
    })
     
    app.listen(3000);
    

    三、koa路由

    3.1 基本实现

    · koa中的路由跟express有所不同,我们需要安装对应的koa-router路由模块来实现

    npm install koa-router --save-dev
    

    引入:

    var koa =require(‘koa’);
    var router=require(‘koa-router’)();
    var app=new koa();
    //ctx 上下文context, 包含了request和response等信息
    router.get(‘/’, async (ctx) => {
       ctx.body=’首页’//相当于res.end( )
    }).get(‘/news’, async (ctx) => { //可以连续使用,也可以分开用
      ctx.body=‘这是一个新闻页面’
    })
    app.use(router.routes())//启动路由
    app.use(router.allowedMethods()) 
    //作用:这是官方文档的推荐用法,
    //我们可以看到router.allowedMethods()用在了路由匹配router.routes()之后,
    //所以在当所有路由中间件最后调用,此时根据ctx.status设置响应头
    app.listen(3000)
    

    3.2 get传值

    如何获取参数?

    方式一:(推荐)

    ctx.query  //打印{aid: ‘123’} 获取的是对象(用的最多的方式)
    ctx.querystring // aid=123&name=zhangsan  获取的是一个字符串
    

    方式二:我们可以从ctx里面的request里面获取get传值

    ctx.request.requery // {aid: ‘123’}
    ctx.quest.querystring // aid=123&name=zhangsan 
    

    3.3 动态路由

    router.get('/newscontent/:aid', async (ctx) => {
       console.log(ctx.params) // { aid : ‘123’}
       ctx.body = '新闻详情'
    })
    

    动态路由可以传入多个值

    router.get('/newscontent/:aid/:cid', async (ctx) => {
       console.log(ctx.params) //{aid:’123’ , cid: ‘456’}
       ctx.body = '新闻详情'
    })
    

    四、koa中间件

    4.1 中间件使用

    中间件的功能:

    · 执行任何代码

    · 修改请求和响应对象

    · 终结请求--响应循环

    · 调用堆栈中的下一个中间件

    如果get、post回调函数中没有next参数,name就匹配上第一个路由,就不会往下匹配了,如果想往下匹配,那么就需要写next()

    4.2 应用级中间件

    · 定义:就是在匹配所有路由之前进行操作某种需求

    const Koa = require('koa');
    const router = require('koa-router')();
    const app = new Koa();
    // 中间件,匹配任何路由,也就是在匹配任何路由之前调用它
    app.use(async(ctx,next)=>{ 
        ctx.body="中间件"
        console.log(new Date())
        await next() // 当前路由匹配完成以后继续向下匹配,不写就不会向下匹配
    })
    router.get('/', async (ctx) => {
        ctx.body = '首页'
    })
    router.get('/news', async (ctx) => {
        ctx.body = '新闻'
    })
    app.use(router.routes()); //启动路由
    app.use(router.allowedMethods())
    app.listen(3000)
    

    4.3 路由中间件

    · 定义: 匹配特定路由前进行某种操作

    router.get('/news', async (ctx,next) => {//匹配到news路由后继续向下匹配路由
      console.log(“新闻中间件”)
    await next()
    })
    router.get('/news', async (ctx) => {
        ctx.body = '新闻'
    })
    

    4.4 错误处理中间件

    · express的中间件和路由有前后顺序,而koa没有顺序,即使放在路由最后面,也先执行中间件

    例子:404页面

    app.use(async(ctx,next)=>{ 
     console.log(‘这是一个中间件01’)
    await next() 
    if(ctx.status==404){
      ctx.status=404;
    ctx.body=”这是一个404页面”
    }else{
      console.log(‘正常’)
    }
    })
    router.get('/', async (ctx) => {
        ctx.body = '首页'
    })
    

    打印结果:这是一个中间件01 -> 首页 -> 正常

    执行顺序,先打印:这是一个中间件01,然后执行next()下面的路由,当执行完路由返回结果后,再回到app.use中间件,执行if判断

    · 这时候我们就要说一下koa的执行模式

    app.use(async(ctx,next)=>{ 
        console.log('中间件01')
        await next() 
        console.log('1')
    })
    app.use(async(ctx,next)=>{ 
        console.log('中间件02')
        await next() 
        console.log('2')
    })
    app.use(async(ctx,next)=>{ 
        console.log('中间件03')
        await next() 
        console.log('3')
    })
     
     
    router.get('/', async (ctx) => {
        ctx.body = '首页'
    })
    router.get('/news', async (ctx) => {
        console.log('匹配到新闻页面')
        ctx.body = '新闻'
    })
    

    执行结果:

    中间件01 ->中间件02 ->中间件03->匹配到新闻页面-> 3 -> 2 -> 1

    koa就像洋葱一样,先执行request,然后再执行response(从外到内,再从内到外)

    如图:

    [图片上传失败...(image-559dff-1692700854499)]

    4.5 第三方中间件

    五、 ejs模板引擎

    5.1 安装 koa-views ejs

    · npm install koa-views --save
    · npm install ejs --save
    

    5.2 使用

    const Koa = require('koa');
    const views =require('koa-views')
    const router = require('koa-router')();
    const app = new Koa();
    // app.use(views(__dirname + '/views', {map: {html: 'ejs'}})) 这种方式文件名得写index.html
    app.use(views(__dirname+'/views', { extension: 'ejs' })) 这种写index.ejs
    router.get('/', async (ctx) => {
      let title=”hello world
      let arr=[‘刚刚’,‘他娃儿噶’,‘大幅度’]
      await ctx.render('index',{  //别忘了加 await
         title:title,
         arr:arr
      })
    })
    

    html部分

    <h1>这是一个ejs的模板引擎</h1>
    <h2><%= title %></h2>
    <ul>
       <% for(var i=0; i<arr.length; i++){ %>
         <li><%= arr[i] %></li>
        <% }%>
    </ul>
    

    5.3 可以引入公共header 和footer

    新建一个header.ejs文件

    <h1>我是公共header</h1>
    然后通过 <%- include('public/header.ejs') -%>引入
    

    5.4 绑定数据

    nodejs部分

    router.get('/', async (ctx) => {
        let content = '<h3>我是数据</h3>'
        await ctx.render('index',{
            content:content
        })
    })
    

    ejs部分

    <%=content%>
    

    可是这样输出的是 <h3>我是数据</h3>,不能解析<h3>标签

    这时候我们需要用<%- %>

    <%-content%>这样就可以了
    

    5.5 条件判断

    router.get('/', async (ctx) => {
       let number=123
        await ctx.render('index',{
           number:number
        })
    })
    

    ejs部分

    <% if(number>20){%>
        <p>大于20</p>
        <%} else {%>
        <p>小于20</p>
    <%}%>
    

    5.6 如何配置公共数据

    · 如果所有的页面都需要同一个数据的时候,该怎么办呢?

    当然你也可以一个页面写一个,但是如果有几十个上百个页面那就太麻烦了,这时候我们就可以在中间件的ctx.state中去定义

    例子:比如每个页面都需要userInfo数据

    我们可以这样做

    nodejs部分

    app.use(anync (ctx,next) =>{
      ctx.state.userInfo=”我是公共数据”
     await next()
    })
    

    ejs调用

    <%=userInfo%>
    

    六、 koa post提交数据

    6.1 nodejs原生实现接收表单请求数据

    ejs部分

    <form action="/doAdd" method="post">
       <label for="">用户名:</label>
       <input type="text" name="username">
       <br>
       <label for="">密码:</label>
       <input type="password" name="password">
       <br>
       <button type="submit">确定</button>
    </form>
    

    nodejs部分

    const Koa = require('koa');
    const views =require('koa-views')
    const router = require('koa-router')();
    const common =require('./module/common.js')
    const app = new Koa();
     
    app.use(views(__dirname+'/views', { extension: 'ejs' }))
    router.get('/', async (ctx) => {
        await ctx.render('index.ejs')
    })
     
    router.post('/doAdd', async (ctx) => {
        var data= await common.getPostData(ctx)
        console.log(data)
        ctx.body=data;
     
    })
     
    app.use(router.routes()); //启动路由
    app.use(router.allowedMethods())
    app.listen(3000)
    

    我们新建了一个module文件夹,在里面新建了一个common.js

    通过node原生代码实现接收客户端请求的数据

    在common.js中封装了一个函数getPostData

    代码如下

    exports.getPostData=function(ctx){
      return new Promise(function(resolve,reject){
        try{
          var str='';
          ctx.req.on('data',function(chunk){
             str+=chunk;
           })
          ctx.req.on('end',function(chunk){
             resolve(str)
          })
        }catch(err){
          reject(err)
        }
     })
    }
    

    6.2 koa-bodyparser获取表单提交的数据

    ①先安装

    npm install koa-bodyparser --save
    

    ② 引入

    const bodyParser =require(‘koa-bodyparser’)
    

    ③配置koa-bodyparser中间件

    app.use(bodyParser())
    

    ④ 获取表单提交的数据

    ctx.request.body
    

    代码如下

    router.post('/doAdd', async (ctx) => {
     var data = ctx.request.body
     ctx.body=data;
    })
    

    七、 koa-static 静态资源中间件

    为什么要用它?

    像css文件,如果只用link引入的话是无效的,这时候就用到了koa-static来处理静态资源

    ① 安装

    npm install koa-static --save
    

    ② 引入

    const static = require(‘koa-static’)
    

    ③ 配置,可以配置多个

    app.use(static(__dirname+'/static')) 
    

    首先去static寻找,如果找到了返回对应的文件,找不到就next()

    注意:link引入的时候,不要写外部的文件夹

    比如:<link rel="stylesheet" href="../static/css/style.css"> 这样写是不行的

    <link rel="stylesheet" href="css/style.css"> 这样写就可以了

    同样,图片引入的时候也不用写static

    八、 art-template模板引擎(看官网)

    art-template 是一个简约、超快的模板引擎。

    它采用作用域预声明的技术来优化模板渲染速度,从而获得接近 JavaScript 极限的运行性能,并且同时支持 NodeJS 和浏览器。

    用两种写法:①跟ejs类似 ② 跟angular类似

    render(app, {
      root: path.join(__dirname, 'view'), //视图
      extname: '.art', //后缀名
      debug: process.env.NODE_ENV !== 'production' //是否开启调试
    });
    

    九、 koa中cookie的使用

    9.1 cookie 简介

    · cookie是存储于访问者的计算机中的变量

    · http协议是无状态的

    · cookie的作用

    ① 保存用户信息

    ② 浏览器历史记录

    ③ 猜你喜欢的功能

    ④ 10天免登陆

    ⑤ 多个页面之间的数据传递

    ⑥ cookie实现购物车功能

    9.2 koa中设置cookie的值

    ctx.cookies.set(name,value,[options])
    

    通过options设置cookie 中name 的value的配置

    cookie的参数

    [图片上传失败...(image-fd84b1-1692700854499)]

    · 实现多个页面之间的cookie共享

    router.get('/', async (ctx) => {
      ctx.cookies.set('userinfo','zhangsan',{
         maxAge:60*1000*60, //多长时间以后过期
         path:’/news’,//特定路径才能访问
        domain:’.baidu.com’,
    // 表示 a. baidu.com  b.baidu.com 可以共享cookie的数据, 
    //正常情况下不要设置,默认就是当前域下面的所有页面都可以访问
          httpOnly:true , 
    //true表示这个cookie只有服务器端可以访问(在页面中通过js访问不到),
    //false表示服务端和都可以访问
        })
        await ctx.render('index.ejs')
    })
    router.get('/news', async (ctx) => {
        var cookdata = ctx.cookies.get('userinfo')
        ctx.body = cookdata;
    })
    

    9.3 koa中的cookie的bug

    · 如果设置cookie的值为中文时会报错

    router.get('/', async (ctx) => {
      ctx.cookies.set('userinfo',‘张三’,{ //会报错
         maxAge:60*1000*60
      })
    })
    

    解决方法:

    运用buffer将汉字转换成base64 字符 ,最后再将base64还原会汉字

    router.get('/', async (ctx) => {
      var userinfo = new Buffer(‘张三’).toString(‘base64’)
      ctx.cookies.set('userinfo',userinfo ,{
        maxAge:60*1000*60                  
     })
      await ctx.render('index.ejs')
    })
    router.get('/news', async (ctx) => {
    var cookdata = ctx.cookies.get('userinfo')
    var userinfo = new Buffer(cookdata ,’base64’).toString()
        ctx.body = userinfo;
    })
    

    相关文章

      网友评论

          本文标题:一文彻底搞懂koa2和ejs

          本文链接:https://www.haomeiwen.com/subject/qolymdtx.html