Node.js(二)——npm包管理器,koa安装及使用,koa中的applition对象及context对象,koa-views,koa-static,koa-router,常见http状态码

84 篇文章 3 订阅
10 篇文章 0 订阅

目录

1.课堂目标及知识点

2.koa介绍

3.koa使用

3.1koa安装

3.2一个简单的koa服务器

3.3Koa 利用中间件 控制"上游",调用"下游“;

4.Application对象

5.上下文context对象常用属性及方法

5.1context 将node中的request和response 封装到一个对象中,并提供一些新的api提供给用户进行操作;

5.2request及response别名

5.2.1koa会把ctx.request上的属性直接挂载到ctx上如:

5.2.2同样也会把ctx.response上的属性直接挂载到ctx上如:

5.2.3ctx.status 获取响应状态。

5.2.4http状态码

6.koa常用中间件——koa-router路由

6.1koa-router安装

6.2Koa-router使用

6.3Koa-router推荐使用RESTful架构API。

7.koa常用中间件——koa-views加载页面

7.1安装 koa-views

7.2使用koa-views

8.koa常用中间件——koa-static

9.使用koa框架重构新闻列表页面


1.课堂目标及知识点

课堂目标

  1. npm包管理器使用
  2. koa使用
  3. 了解koa中的applition对象及context对象
  4. koa-views使用
  5. koa-static使用
  6. 使用koa-router中间件搭建路由
  7. 了解常见http状态码

本节知识点

  1. http模块实现模板加载及静态文件处理
  2. koa的安装及使用
  3. Application及context对象介绍
  4. 常用http状态码介绍
  5. 路由中间件koa-router介绍
  6. 中间件koa-views介绍

2.koa介绍

  1. koa是express原班人马打造的轻量级、健壮性、富有表现力的nodejs的框架
  2. 目前koa有koa1和koa2两个版本;
  3. koa2依赖Node.js 7.6.0或者更高版本
  4. koa不在内核方法中绑定任何中间件,它仅仅是一个轻量级的函数库,几乎所有功能都必须通过第三方插件来实现

3.koa使用

3.1koa安装

$ npm i koa

3.2一个简单的koa服务器

const Koa = require('koa');
const app = new Koa();
​
app.use(async ctx => {
  ctx.body = 'Hello World';
});
​
app.listen(3000);

3.3Koa 利用中间件 控制"上游",调用"下游“;

  • koa是包含一组中间件函数的对象;可以将app.use里的函数理解成中间件
  • ctx即context上下文,是原来node.js的req和res的合体分别对应ctx.req、ctx.res,context会将res和req封装成ctx.request和ctx.respones;
//这里的middleWare函数就是一个中间件
let middleWare = async (ctx,next)=>{
    console.log("first middleWare");
    ctx.body = "hello world";
}
app.use(middleWare);
  • 通过next()将控制转交给另一个中间件;有next()函数才会执行下一个中间件。next()调用后才会执行中间件,不调用则不会执行
  • 一般都是使用第三方提供的中间件。
  • 中间件中如果有异步逻辑,通过async await处理(await后跟的一定是promise对象);async await同步写法实现异步功能
  • 上述过程也可以通过"洋葱模型“来解释中间件执行顺序

中间件执行示例:有next()函数才会执行下一个中间件。如此处next()调用后才会执行中间件,不调用则不会执行

//node.js的框架koa
const Koa = require("koa");
const app = new Koa();

const middleWare3 = require("./m3");

//中间件
let middleWare1 = (cxt, next) => {
    console.log("one start......");

    cxt.body = "hello world11111";
    //当前表示中间件转交给下一个中间件,有next()函数才会执行下一个中间件。如此处next()调用后才会执行中间件,不调用则不会执行
    next();
    console.log("one end......");
}


let middleWare2 = (cxt, next) => {
    console.log("two start......");
    cxt.body = "hello world22222";
    next();
    console.log("two end......");
}

app.use(middleWare1);
app.use(middleWare2);
// 中间件也可以是引入方式
app.use(middleWare3);
/*
    中间件执行结果:
    one start......
    two start......
    three start........
    three end ..........
    two end......
    one end......
 */

//  app.on("error",(err)=>{
//      console.log(err);
//  });
app.listen(4000);

中间件执行结果:
    one start......
    two start......
    three start........
    three end ..........
    two end......
    one end......

4.Application对象

  • application是koa的实例 简写app
  • app.use 将给定的中间件方法添加到此应用程序,分为同步和异步,异步:通过es7中的async和await来处理
  • app.listen设置服务器端口;
  • app.on 错误处理;

5.上下文context对象常用属性及方法

5.1context 将node中的request和response 封装到一个对象中,并提供一些新的api提供给用户进行操作;

  • ctx.app:应用程序实例引用,等同于app;
  • ctx.req:Node 的 request 对象.
  • ctx.res:Node 的 response 对象.
  • ctx.request:koa中的Request对象;
  • ctx.response:koa中的response对象;
  • ctx.state:对象命名空间,通过中间件传递信息;
  • ctx.throw:抛出错误;

错误处理:

//  错误处理
 app.on("error",(err)=>{
     console.log(err);
 });

5.2request及response别名

5.2.1koa会把ctx.request上的属性直接挂载到ctx上如:

  • ctx.header //头信息;
  • ctx.headers
  • ctx.method
  • ctx.method=ctx.request.method
  • ctx.url
  • ctx.url=ctx.request.url

5.2.2同样也会把ctx.response上的属性直接挂载到ctx上如:

  • ctx.body
  • ctx.body=ctx.response.body
  • ctx.status
  • ctx.status=ctx.response.status

5.2.3ctx.status 获取响应状态。

默认情况下,response.status 设置为 404 而不是像 node 的 res.statusCode 那样默认为 200

原生js和原生node.js中可以通过ctx.setHeader和ctx.writeHead()进行设置

5.2.4http状态码

  • http状态码:1xx(消息)、2xx(成功)、3xx(重定向)、4xx(请求错误)、5xx和6xx(服务器错误)

  • 常见http状态码 (302 location 跳转)

     
    HTTP状态码描述
    100继续。继续响应剩余部分,进行提交请求
    200成功
    301永久移动。请求资源永久移动到新位置
    302临时移动。请求资源零时移动到新位置
    304未修改。请求资源对比上次未被修改,响应中不包含资源内容
    401未授权,需要身份验证
    403禁止。请求被拒绝
    404未找到,服务器未找到需要资源
    500服务器内部错误。服务器遇到错误,无法完成请求
    503服务器不可用。零时服务过载,无法处理请求
  • 设置状态码

一般在获取成功或失败数据。如{info:"请求成功",status:0}以外,还需要给浏览器给出状态码,才更符合浏览器的规则

router.get("/getData", async (cxt,next)=>{
    //cxt.status设置状态码
    //302临时跳转,会跳转到设置的地址
    cxt.status = 302;
    // 设置头部
    cxt.set("location","http://www.baidu.com");
    cxt.body = {
        name:'lmf',
        age:23
    };
});

6.koa常用中间件——koa-router路由

  • 路由是引导匹配之意,是匹配url到相应处理程序的活动。

6.1koa-router安装

npm i koa-router -S

6.2Koa-router使用

  • 请求方式:get/post/put/delete等;
  • 使用localhost:5000和localhost:5000/地址是一样的
  • koa框架中cxt.body会将对象数据直接转换为json数据格式
  • 使用app.use(router.routes());将app(koa框架)和router进行关联
  • koa-router中加载文件必须使用异步才能加载到文件,async await时同步写法实现异步功能,await后必须返回的是promise对象,此处await后,cxt.render()底层有返回promise对象
//中间件koa-router
const Koa = require("koa");
const Router = require("koa-router");

let app = new Koa();
let router = new Router();

//请求方式:get / post /put /delete 等
//直接打印"/"和什么都不输入一样
router.get("/",async (cxt,next)=>{
    cxt.body = "hello world";
});

//传输对象格式数据(cxt.body会将对象数据直接转换为json数据)
//{"name":"lmf","age":23}
router.get("/getData", async (cxt,next)=>{
    //cxt.status设置状态码
    //302临时跳转,会跳转到设置的地址
    cxt.status = 302;
    cxt.set("location","http://www.baidu.com");
    // koa会直接将对象转为json
    cxt.body = {
        name:'lmf',
        age:23
    };
});

// 通过此句将app和router进行关联
app.use(router.routes());
app.listen("5000");

6.3Koa-router推荐使用RESTful架构API。

Restful的全称是Representational State Transfer 即表现层转移。

  • RESTful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。基于这个风格设计可以更简洁,更有层次;
  • 非RESTful架构api:
  • 使用RESTful架构设计api

REST设计一般符合如下条件:

  • 程序或者应用的事物都应该被抽象为资源
  • 每个资源对应唯一的URI(uri是统一资源标识符)
  • 使用统一接口对资源进行操作
  • 对资源的各种操作不会改变资源标识
  • 所有操作都是无状态的(如session等)

一般的请求接口:

  • www.test.com:/90/addUser 增加
  • www.test.com:/90/deleteUser 删除
  • www.test.com:/90/updateUser 修改
  • www.test.com:/90/getUser 获取

REST设计的请求接口:接口地址都一样,而是通过请求方式的不同跳转到不同的方法。

  • www.test.com:/90/user 增加 post
  • www.test.com:/90/user 删除 delele
  • www.test.com:/90/user  修改 put
  • www.test.com:/90/user  获取 get

好处:

  • 这种方式更符合浏览器规则;
  • 在做多终端(PC端,安卓,ios等)时请求都可以通用;
  • 接口抽象出来;
  • 有统一的标识符
  • 无状态原则,session等会话状态是不会保存的。所以这些就只能通过前端通过cookie进行保存,或者现有的解决方法jwt(json web token)

7.koa常用中间件——koa-views加载页面

  • koa-views用于加载模板文件;
  • 可以是任何类型的文件:html,也可以是模块文件(pug或nunjucks)
  • 使用pug模板文件时,必须加载文件后缀名。如index.pug。
  • nunjucks使用时不使用koa-views模块而是使用koa-nunjucks-2模块

7.1安装 koa-views

npm i koa-views -S

7.2使用koa-views

koaviews.js:

注意:可以是任何类型的文件:html,也可以是模块文件(pug或nunjucks),nunjucks使用时不使用koa-views模块而是使用koa-nunjucks-2模块

koa-router中加载文件必须使用异步才能加载到文件,async await同步写法实现异步功能,await后必须返回的是promise对象,此处await后,cxt.render()底层有返回promise对象。

//koa-view 渲染页面的中间件
const Koa = require("koa");
const Router = require("koa-router");
// 注意是koa-views不是koa-view 
const views = require("koa-views");

let router = new Router();
let app = new Koa();

//koa-views设置文件路径和文件类型(路径views一定要和项目中页面文件路径一致)
app.use(views(__dirname+"/views"),{
    //可以是任何类型的文件:html,也可以是模块文件(pug或nunjucks),nunjucks使用时不使用koa-views模块而是使用koa-nunjucks-2模块
    map:{
        html:"pug"
    }
});

//koa-router中加载文件必须使用异步才能加载到文件,async await同步写法实现异步功能,await后必须返回的是promise对象,此处await后,cxt.render()底层有返回promise对象
router.get("/",async (cxt,next)=>{
    // 注意使用pug时,一定要有pug后缀
    await cxt.render("index.pug");
});

app.use(router.routes());
app.listen(8989);

index.pug:

<!DOCTYPE html>
html(lang="en")
    head
        meta(charset="UTF-8")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title Document
    body
        h1 pug页面

8.koa常用中间件——koa-static

  • koa-static 是用于加载静态资源的中间件,通过它可以加载css、js等静态资源;

  • 安装 koa-static

    npm i koa-static

  • 使用koa-static

//koa-static 加载静态文件
const Koa = require("koa");
const Router = require("koa-router");
const views = require("koa-views");
const static = require("koa-static");

let router = new Router();
let app = new Koa();

//koa-view设置设置文件路径和文件类型
app.use(views(__dirname+"/views"),{
    map:{
        html:'pug'
    }
});

//koa-static加载静态文件(注意static不需要再写)
app.use(static(__dirname+"/static"));

//koa-router中加载文件(必须使用异步才能加载到文件)
router.get("/",async (cxt,next)=>{
    await cxt.render("index.pug");
});

app.use(router.routes());
app.listen("7000");

index.css:

h1 {
    color:red;
}

index.pug:

<!DOCTYPE html>
html(lang="en")
    head
        meta(charset="UTF-8")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title Document
        link(rel="stylesheet", href="/css/index.css")
    body
        h1 pug页面

9.使用koa框架重构新闻列表页面

注意点:

  • 使用static后,在页面再引入静态页面,css,js,img等时路劲就不需要再写到static级;
  • 使用cxt.render时,必须使用async await异步加载页面;
  • 在node.js版本5.1之前通过命令:npm i 模块名 -S时,会自动创建package.json文件,但5.1之后只会自动创建package-lock.json文件(这个文件比package.json文件中的描述内容更加详尽),所以每次创建项目后,必须手动通过npm i在项目路径下创建package.json文件。创建之后,再通过命令 npm i 模块名 -S 安装某个模块时,才会将描述信息覆盖到package.json文件中。且-S会自动写入dependencies ,-D会自动写入devDependencies。另外使用cnpm命令创建模块时只会自动创建package.json文件,不会创建package-lock.json文件,但是不推荐使用cnpm命令。

koa框架重构新闻列表页面完整示例:

index.js:注意需要路由页面时,需要将所有页面需要的数据推送过去

const Koa = require("koa");
const Router = require("koa-router");
const views = require("koa-views");//注意是koa-views
const static = require("koa-static");
const url = require("url");
//注意要使用pug,必须导入pug
const pug = require("pug");

//cheerio实现类JQuery功能
const cheerio = require("cheerio");

let data = require("./data/data.json");

let app = new Koa();
let router = new Router();

//可以再views时设置,对应的页面后缀(注意此处设置模板也是views方法的参数)
app.use(views(__dirname + "/views", {
    map: {
        html: 'pug'
    }
}));
// 使用static后,在页面再引入静态页面,css,js,img等时路劲就不需要再写到static级
app.use(static(__dirname + "/static/css"));
app.use(static(__dirname + "/static/img"));

//新闻列表显示
//注意使用cxt.render时,必须使用async await异步加载页面
router.get("/news/index", async (cxt, next) => {
    //分页
    let pageNum = url.parse(cxt.url,true).query.p || 1;
    //通过pageNum进行分页
    let pageSize = 5;
    
    let pageTotal = Math.ceil(data.length / pageSize);
    // 0-4  5-10  ((pageNum-1)*pageSize,pageNum*pageSize)
    let curData = data.slice((pageNum-1)*pageSize,pageNum*pageSize);

    //render是方法,不是属性,且文件必须写后缀
    await cxt.render("viewlist.pug", {
        curData,
        pageTotal,
        pageNum
    });
});

//新闻详细也显示
router.get("/news/detail", async (cxt, next) => {
    //分页
    let id = url.parse(cxt.url,true).query.id || 1;

    let detailData = data.find(item=>id == item.id);
    //render是方法,不是属性,且文件必须写后缀
    await cxt.render("detail.pug", {
        detailData
    });
});

app.use(router.routes());

app.listen("8989");

viewlist.pug:

meta(charset='UTF-8')
meta(name='viewport', content='width=device-width,initial-scale=1')
meta(http-equiv='X-UA-Compatible', content='ie=edge')
link(rel='stylesheet', href='../index.css')
title 文章信息展示
.wrap
  ul.news-list
    each item in curData
      li.news
        a(href='javascript:;')
          img(src='../img.png', alt)
        div
          h3
            a(href='/news/detail?id='+item.id) #{item.title}
          .info
            span.tips
              span #{item.publisher}
            //  <span class="line"></span> 
            span.time |   #{item.time}
.pagination
  - let p = parseInt(pageNum);
    a.prev(href=`/news/index?p=${Math.max(1,p-1)}`) ⌜
      - for(let i=1;i<=pageTotal;i++)
        - if(p == i)
          a(href='/news/index?p='+i class="active") #{i}
        - else
          a(href='/news/index?p='+i) #{i}
    a.next(href=`/news/index?p=${Math.min(pageTotal,p+1)}`) ⌝

detail.pug:

meta(charset='UTF-8')
meta(name='viewport', content='width=device-width,initial-scale=1')
meta(http-equiv='X-UA-Compatible', content='ie=edge')
title Document
style.
  
  .text{
              width: 640px;
              margin: 0 auto;
          }
          .article-info{
              color:#999;
              font-size: 14px;
          }
          p{
              font-size: 16px;
              line-height: 30px;
          }
  
.text
  h1.title #{detailData.title}
  .article-info 类型:#{detailData.publisher} 时间:#{detailData.title}
  p.content.
    
    #{detailData.title}
    

data.json:数据作相应更改

[
    {
        "id": 1,
        "title": "13岁少年成暴徒,这才是社会的灾难",
        "publisher": "海外网",
        "time": "今天 17:08"
    },
    {
        "id": 2,
        "title": "举行新闻发布会(全文实录)",
        "publisher": "中国网",
        "time": "今天 16:59"
    },
    {
        "id": 3,
        "title": "XX学校禁读《哈利·波特》 称咒语召唤邪灵",
        "publisher": "澎湃新闻",
        "time": "今天 16:56"
    },
    {
        "id": 4,
        "title": "XXXXXXX滚回去",
        "publisher": "海外网",
        "time": "今天 16:54"
    },
    {
        "id": 5,
        "title": "西XX职位空缺190天后,迎来XX王浩",
        "publisher": "上游新闻",
        "time": "今天 16:54"
    },
    {
        "id": 6,
        "title": "中国游客在日本突然昏迷 2名韩国消防员及时相救",
        "publisher": "海外网",
        "time": "今天 16:53"
    },
    {
        "id": 7,
        "title": "XX零售雪上加霜 奢侈品牌普拉达将关闭在XX最大门店",
        "publisher": "观察者网",
        "time": "今天 16:46"
    },
    {
        "id": 8,
        "title": "拖了18年,XX为何此时从XXX?",
        "publisher": "海外网",
        "time": "今天 16:41"
    },
    {
        "id": 9,
        "title": "XXXXX?XXXX:系误读",
        "publisher": "环球网",
        "time": "今天 16:37"
    },
    {
        "id": 10,
        "title": "被男议员骂“不生孩子没尽国家责任” 韩国55岁女学者懵了",
        "publisher": "海外网",
        "time": "今天 16:29"
    },
    {
        "id": 11,
        "title": "中国XXXXX被提起公诉",
        "publisher": "XXX察院",
        "time": "今天 16:29"
    },
    {
        "id": 12,
        "title": "XXX假装尿急翻墙逃出营区 10天后在网吧被抓",
        "publisher": "海外网",
        "time": "今天 16:22"
    },
    {
        "id": 13,
        "title": "XXX“罢课演讲”出糗:成语连说了3遍都没对",
        "publisher": "海外网",
        "time": "今天 16:21"
    },
    {
        "id": 14,
        "title": "XXX、西安市XXX",
        "publisher": "澎湃新闻网",
        "time": "今天 16:09"
    },
    {
        "id": 15,
        "title": "XXX:少数暴徒目的在于搞乱XX 进而XXXX",
        "publisher": "新京报网",
        "time": "今天 16:00"
    },
    {
        "id": 16,
        "title": "XXXXX",
        "publisher": "新京报即时新闻",
        "time": "今天 15:53"
    },
    {
        "id": 17,
        "title": "XX“双普选”:必须符合XX政治地位",
        "publisher": "新京报即时新闻",
        "time": "今天 15:46"
    },
    {
        "id": 18,
        "title": "XX是否认为现在XX局势适用紧急法?XXX回应",
        "publisher": "中国网",
        "time": "今天 15:41"
    },
    {
        "id": 19,
        "title": "XX是否对XX事态设最后期限?XX回应",
        "publisher": "新京报即时新闻",
        "time": "今天 15:35"
    },
    {
        "id": 20,
        "title": "XX发言人:已到维护“XXX”底线的重要关头",
        "publisher": "新京报即时新闻",
        "time": "今天 15:18"
    },
    {
        "id": 21,
        "title": "商务部:上周猪肉批发价格上涨8.9%",
        "publisher": "新京报即时新闻",
        "time": "今天 15:14"
    },
    {
        "id": 22,
        "title": "XXX出糗:这个成语连说三遍都没对",
        "publisher": "海外网",
        "time": "今天 14:54"
    },
    {
        "id": 23,
        "title": "两高:高考等4类考试组织作弊属犯罪 最高判7年",
        "publisher": "新京报即时新闻",
        "time": "今天 14:33"
    }
]

index.css:

body {
    margin: 0;
}

ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

a {
    text-decoration: none;
    color: #404040;
}
.wrap{
    width: 600px;
    margin: 0 auto;
}

.news-list {
    width: 600px;
}

.news {
    width: 100%;
    display: flex;
    justify-content: space-between;
    padding: 15px 0;
    border-bottom: 1px solid #999;
}

.info {
    display: flex;
    width: 170px;
    justify-content: space-between;
    font-size: 12px;
    color: #888;
}

.tips {
    display: flex;
    width: 100px;
    justify-content: space-between;
}

.news-list li:nth-child(5) {
    border-bottom: none;
}
.pagination{
    display: flex;
    width: 210px;
    text-align: center;
    background-color: rgb(252, 238, 238);
    border-radius: 25px;
    overflow: hidden;
    margin: 0 auto;
    justify-content: center;
}
.pagination a{
    width: 30px;
    line-height: 30px;
    color: #404040;
}
.pagination a:nth-child(1) {
    transform: rotate(-45deg) ;
}
.next {
    transform: rotate(45deg) ;
}
.pagination a:hover{
    color: rgb(247, 73, 73);
}
.news div{
    width:420px;
}
.pagination .active {
    color: rgb(247, 73, 73);
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值