node(三)

新闻页的 详细页优化

const http = require("http");
const fs = require("fs");
const mime = require("./data/mime.json");
const path = require("path");
const cheoor = require("cheerio");//外置模块新模块 -> 处理HTML -> 需要init,然后安装cheerio -S
const url = require("url");//内置模块 -> 可以提取路由地址;
let newsData = require("./data/data.json");
let server = http.createServer((req,res)=>{
    let objPath = url.parse(req.url,true);//可以拿到真正的路由地址
    let pathName = objPath.pathname;
    // console.log(pathName);
    if(pathName==="/news" || req.url==="/"){
        res.setHeader("Content-type","text/html;charset=utf-8");
        // res.end("新闻页面");

        // 分页相关;
            // 已知: 当前是那页 页码 : 1,2,3
            // 已知: 每页有多少条? 
            // 得到数据
        // 接收当前页码
        // console.log(objPath.query.p);
        let p = objPath.query.p || 1;//页码
        let perPage = 5;//条
            // 1,5 0-5 -> (p-1)*perPage,perPage
            // 2,5 5,10 -> (p-1)*perPage,perPage
            // ... splice
        let nData = JSON.parse( JSON.stringify(newsData)).splice((p-1)*perPage,perPage);

        // 生成页码
        let totalCount = newsData.length;
        let page = Math.ceil(totalCount/perPage);//页码总数

        // 按照数据组装HTML
        let newHTML = "";
        nData.forEach(itme=>{
            newHTML += `
                <li class="news">
                    <a href="javascript:;">
                        <img src="${itme.imgUrl}" alt="">
                    </a>
                    <div>
                        <h3>
                            <a href="/detail?d=${itme.id}">${itme.title}</a>
                        </h3>
                        <div class="info">
                            <span class="tips"><span>${itme.from}</span></span>
                            <!-- <span class="line"></span> -->
                            <span class="time">| &nbsp;&nbsp;${itme.newTime}</span>
                        </div>
                    </div>
            </li>
            `;
        });

        // 组装分页
        let paginationHtml = `<a href="javascript:;" class="prev">⌜</a>`;
        for(let i = 1;i<=page;i++){
            paginationHtml += `<a href="/news?p=${i}">${i}</a>`;
        }
        paginationHtml += `<a href="javascript:;" class="next">⌝</a>`;

        let indexData = fs.readFileSync("./views/index.html");
        
        let $ = cheoor.load(indexData);//加载处理模板
        $(".news-list").html(newHTML);//替换内容
        $(".pagination").html(paginationHtml);

        // res.end(indexData);
        res.end($.html())
    }else if(pathName==="/detail"){
        res.setHeader("Content-type","text/html;charset=utf-8");
        // 获取后缀内容(?d=)
        let num = parseInt(objPath.query.d);
        // console.log(typeof num);//string
        let detailMessage = newsData.find(item=>item.id===num);
        // 内容;
        let detailHtml = `
            <h1 class="title">${detailMessage.title}</h1>
            <div class="article-info"> ${detailMessage.from} 时间:${detailMessage.newTime}</div>
            <p class="content">
                ${detailMessage.title}
            </p>
        `;
        
        // res.end("详细页面")
        let detailData = fs.readFileSync("./views/detail.html");
        let $ = cheoor.load(detailData);//加载处理模板
        $(".text").html(detailHtml);//替换内容
        res.end($.html());
    }else{
        if(pathName!=="/favicon.ico"){
            let extName = path.extname(req.url);//获取后缀名
            res.setHeader("Content-type",mime[extName]);//配置协议头
            
            let resData = fs.readFileSync("."+req.url);
            res.end(resData);
        }
    }
});
server.listen(8787);

koa

node.js的框架

koa安装

因为不是内置模块~
  npm init -y
  npm i koa -S

Koa构建简单服务端

index.js

const Koa = require("koa");//引用koa
// 通过koa构建服务器:
let app = new Koa();
app.use((ctx,next)=>{
    ctx.body = "hello world";//输出
});
app.listen(8989);//指定端口号

Koa介绍及简单使用

// 官方文档: https://koa.bootcss.com/
const Koa = require("koa");//引用koa
// 通过koa构建服务器:
let app = new Koa();
// ctx context -> 上下文; req/res合并到了ctx;
    // ctx.req => res.request;
    // ctx.res => res.response;
    // ctx.request; ctx.response;
    // http.cteateServer((req,res)=>{})
    // 也就是ctx做了封装
app.use((ctx,next)=>{
    // console.log(ctx.request.query);//获取地址栏 和 原生的url模块很相似
    // ctx.body = "hello world";//输出
    // ctx.body = "hello world你好";//并不会出现乱码;所以koa比原生方便很多
    {
        // 别名
        // res.write();
        // ctx.body === ctx.response.body;
        // ctx.headers === ctx.request.headers;
    }
    /* ctx.body = {//对象自动转为了 JSON 形式
        name:"张三",
        age:20
    } */
    /* ctx.response.body = {//输出结果和上面一样
        name:"李四",
        age:20
    } */
});
app.listen(8989);//指定端口号

koa中间件

home.js

const Koa = require("koa");
let app = new Koa();
// 使用 中间件->函数
    // 中间件也就是一个没有执行函数差不多
let m1 = async function(ctx,next){
    console.log("m1...start");
    // ctx.body = '111';//会被下面的覆盖
    ctx.state = 10;//可以传参数
    await next();//不使用下面的m2就执行不了; 具体情况看需不需要使用 -> 把控制权转移给下一个中间件
    console.log("m1..end");
}
let m2 = async function(ctx,next){
    console.log("m2..start");
    // console.log(ctx.state);
    ctx.body = "我是m2中间件";
    await next();
    console.log("m2...end");
}
let m3 = async function(ctx,next){
    console.log("m3...start");
    ctx.body = "我是m3中间件";
    await next();
    console.log("m3...end");
    /* 
        打印结果为:
            m1...start
            m2..start
            m3...start
            m3...end
            m2...end
            m1..end
        为什么会有这样的结果呢?
            m1的next()可以理解为:
                m2();
                也就是调用了下一个中间件;
                所以很像洋葱执行
                    一层一层打开开,然后回响(最里面出来)
            最后一个m3为什么要next()呢?
                为了后面的中间件
                    ctx.body = "最终"
    */
}
app.use(m1);
app.use(m2);
app.use(m3);
app.use(async ctx=>{
    // 如果有异步,可以使用async和await 但是每一个都需要async和await
    let result = await new Promise(resolve=>{
        setTimeout(()=>{
            resolve("异步输出")
        },1000)
    })
    console.log(result);
    // ctx.body = "最终输出";
    ctx.body = result;
});
app.listen(8787);

koa状态码

myindex.js

const Koa = require("koa");
let app = new Koa();
app.use(async ctx=>{
    // ctx.status = 404;//设置状态码
    // 200,200; ctx.body = {info:"success",status:1}; ctx.body = {info:"fail",status:0}; 这样可以设置对应的状态码,但是不推荐,若知道失败或错误,可以直接去返还状态码做呈现;
        // ctx.status = 302;
        // ctx.set("location","http://www.baidu.com")
        // 因为这些状态码是有一些功能的

    // ctx.set("mycontent","test");//可以设置头部
    ctx.body = "hello";
})
app.listen(8787)

 

上一篇:Koa2中使用art-template模板和静态资源托管


下一篇:使用 Koa 搭建前端服务