文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

​好程序员web前端培训分享node学习笔记系列之四十一

2023-06-03 10:05

关注

好程序员web前端培训分享node学习笔记系列之四十一

一、手动封装body-parser中间件 cookie-parser中间件

1、封装axios请求方式

body-parser

const qs = require("querystring");var bodyparse = (function bodyparse() {

    function common(type) {

        return (req, res, next) => {

            let contentType = req.headers["content-type"];

            if(contentType == "application/json" || contentType == "application/x-www-form-urlencoded"){

                let str = "";

                req.on("data",(data)=>{

                    str+=data;

                })

                req.on("end",()=>{

                    if(contentType == "application/json"){

                        req.body = JSON.parse(str);

                        next();

                    }else if( contentType == "application/x-www-form-urlencoded"){

                        req.body = qs.parse(str);

                        next();

                    }

                    next();

                })

            }else{

                next();

            }

        }

    }

    //解析appliaction/json    function json() {

        let type = "json"

        return common(type)

    }

    //解析appliaction/x-www-form-urlencoded    function urlencoded() {

        let type = "urlencoded";

        return common(type)

    }

    return { json, urlencoded }})()module.exports = bodyparse;

cookie-parser

const cookieparse = function(){

    return (req,res,next)=>{

        let cookies = req.headers.cookie;

        let obj = cookies.split("; ").reduce((prev,curr)=>{

            var key = curr.split("=")[0];

            var val = curr.split("=")[1];

            prev[key] = val;

            return prev;

        },{})

        req.headers.cookie = obj;

        next();     

    }}module.exports = cookieparse;

二、express原理解析

1、app.use的作用以及实现

const http = require("http")const url = require("url");const path = require("path");const fs = require("fs");const express = () => {

    //将所有注册的事件添加到routesMap中去    var routesMap = {

        get: {

        },

        post: {

        }

    }

    //app这个函数中做的执行    var app = function (req, res) {

        //获取用户请求的路径        var pathname = url.parse(req.url).pathname;

        //获取用户请求的方式        var method = req.method.toLowerCase();

        if (pathname !== "/favicon.ico") {

            //next函数用来执行下一个中间件            var next = function () {

                var handle;

                //执行是没有路径的函数                while (handle = routesMap.all.shift()) {

                    handle(req, res, next)

                }

            }

            next();

            //执行app.use带路径的函数              for (var key in routesMap) {

                //判断路径是否与用户请求的路径相同                if (key === pathname) {

                    routesMap[key](req, res, next);

                    break;

                }

            }

            //判断用户是否是get请求            if (method == "get") {

                //如果是get请求则找到get请求相对应得路径 执行对应的函数                for (var key in routesMap.get) {

                    if (key == pathname) {

                        routesMap.get[key](req, res, next);

                        break;

                    }

                }

            } else if (method == "post") {

            }

        }

    }

    //注册事件    app.use = function () {

        //判断use中的第一个参数是路径还是一个函数        if (typeof arguments[0] === "string") {

            routesMap[arguments[0]] = arguments[1]

        } else if (typeof arguments[0] === "function") {

            //建议all这个key值写成Symbol            if (!routesMap.all) {

                routesMap.all = [];

            }

            routesMap.all.push(arguments[0]);

        }

    }

    //注册事件    app.get = function (path, callback) {

        routesMap.get[path] = callback;

    }

    //创建服务    app.listen = function (port, callback) {

        http.createServer(app).listen(port, callback)

    }

    return app;}//静态资源访问express.static = function (staticPath) {

    function getFile(filePath) {

        return fs.readFileSync(filePath);

    }

    return (req, res) => {

        var { pathname } = url.parse(req.url, true);

        //获取文件的后缀        var ext = pathname.substring(pathname.lastIndexOf("."));

        if (pathname === "/") {

            res.writeHead(200, { "content-type": "text/html;charset=utf8" });

            res.end(getFile(path.join(staticPath, "index.html")))

        } else if (ext === ".css") {

            res.writeHead(200, { "content-type": "text/css;charset=utf8" });

            res.end(getFile(path.join(staticPath, pathname)));

        } else if (ext === ".js") {

            res.writeHead(200, { "content-type": "application/x-javascript;charset=utf8" });

            res.end(getFile(path.join(staticPath, pathname)));

        } else if (/.*\.(jpg|png|gif)/.test(ext)) {

            res.writeHead(200, { "content-type": `image/${RegExp.$1};charset=utf8` });

            res.end(getFile(path.join(staticPath, pathname)));

        } else if (ext === ".html") {

            res.writeHead(200, { "content-type": "text/html;charset=utf8" });

            res.end(getFile(path.join(staticPath, pathname)));

        }

    }}module.exports = express;

三、express-generator生成器以及代码解析

1、app.js解析

2、www文件解析

3、ejs的基本使用

用<% … %> 开始符和结束符之间写js代码用<%= … %>输出变量数据 变量若包含 '<' '>' '&'等字符 会被转义用<%- … %>输出变量(html的解析前面需要加-) 不转义用<%- include('user/show') %>引入其他模板 包含 ./user/show.ejs用<%# some comments %>来注释,不执行不输出<%% 转义为 '<%'<% ... -%> 删除新的空白行模式?<%_ … _%> 删除空白符模式开始符和结束符内部不可以嵌套

四、前端渲染和后端渲染的区别

后端渲染HTML的情况下,浏览器会直接接收到经过服务器计算之后的呈现给用户的最终的HTML字符串,这里的计算就是服务器经过解析存放在服务器端的模板文件来完成的,在这种情况下,浏览器只进行了HTML的解析,以及通过操作系统提供的操纵显示器显示内容的系统调用在显示器上把HTML所代表的图像显示给用户。前端渲染就是指浏览器会从后端得到一些信息,这些信息或许是适用于题主所说的angularjs的模板文件,亦或是JSON等各种数据交换格式所包装的数据,甚至是直接的合法的HTML字符串。这些形式都不重要,重要的是,将这些信息组织排列形成最终可读的HTML字符串是由浏览器来完成的,在形成了HTML字符串之后,再进行显示

五、用所学的express生成器+ejs做一个简单的列表页

六 、socket的基本使用

1、什么是socket?

网络上两个程序通过一个双向的通信连接实现数据交换,这个连接的一端称为socket

2、http请求与socket的区别

在以前我们实现数据交换已经有了HTTP协议,为什么还要学习socket? 回顾:当输出www.baidu.com的时候浏览器执行了那些操作?2、http通信的特点:1、连接属于非持久性连接:TCP的三次握手2、客户端只能访问服务端,服务端无法访问客户端,属于单项通信TCP三次握手: TCP三次握手过程中不传递数据,只为同步连接双方的序列号和确认号传递数据,在握手后服务端和客户端才开始传输数据,在理想状态下,TCP连接一旦建立,在通信的双方中任何一方主动断开连接之前TCP连接会一直保持下去。socket通信特点:1、持久性连接2、双向通信,客户端能访问服务端,服务端也能访问客户端socket是对TCP/IP协议的封装,socket只是一个接口而不是一个协议,通过Socket我们才能使用TCP/IP/UDP协议

3、通过node内置模块net实现简单版聊天

socket连接需要由2个节点:(1)clientSocket(2)serverSocket2、文本流:readline

const net = require("net");const server = net.createServer();const clients = [];//当有人连接服务端的时候回触发当前函数server.on("connection",(client)=>{

    //给每一个用户添加一个唯一的标识    client.id = clients.length;

    clients.push(client);

    //将客户端的消息转发给所有的用户    client.on("data",(data)=>{

        clients.forEach(item=>{

            //判断用户是否存在            if(item) item.write("服务端:"+data);

        })

    })

    //判断用户是否退出群聊    client.on("close",()=>{

        clients[client.id] = null;    

    })})server.listen(9000);const net = require("net");const client = new net.Socket();//创建I/o模型 创建出入和输出流const readline = require("readline");//创建const rl = readline.Interface({

    input: process.stdin,

    output: process.stdout})//客户端连接服务端client.connect(9000, () => {

    client.on("data", (data) => {

        console.log(data.toString());

    })})//获取终端的内容将内容转发到服务端rl.on("line", (val) => {

    client.write(val);})

七、webSocket的基本使用

const WebSocket = require('ws');//创建服务const server = new WebSocket.Server({ port: 9000 });//监控用户连接server.on('connection', (client,req)=>{

   var ip = req.connection.remoteAddress;

    //监听客户端传递到服务端的消息    client.on('message', (data)=>{

        //将消息转发给所有的用户        server.clients.forEach((item)=>{

            //判断用户是否是连接的状态            if (item.readyState === WebSocket.OPEN) {

                item.send(ip+":"+data);

            }

        });

    });});

<!DOCTYPE html><html lang="en"><head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>Document</title></head><body>

    <input type="text" id="txt">

    <button id="btn">点击</button>

    <ul id="list"></ul></body></html><script>

    var client = new WebSocket("ws://10.60.15.150:9000");

    var txt = document.getElementById("txt");

    var list = document.getElementById("list");

    var btn = document.getElementById("btn");

    //接受服务端消息  onmessage    client.onmessage = function(e){

       var li = document.createElement("li");

       li.innerText = e.data;

       list.appendChild(li);

       li.scrollIntoView();

    }

    //向服务端发送消息 send    btn.onclick = function(){

        var val = txt.value;

        client.send(val);

        txt.value = "";

    }</script>

八、http://socket.io的基本使用

var express = require('express')var app = express();//文件在服务器运行var http = require('http')var server = http.createServer(app);var path = require("path")//因为我们要做持久性通信 因此不能够用http连接 http连接与socket.io进相关联var io = require("socket.io")(server);app.use(express.static(path.join(__dirname,"./public")))//当用户连接的时候触发的函数io.on('connection', (socket)=>{

    console.log('a user connected');

    //接受客户端消息 将消息转发给所有用户    socket.on("sendMessage",(mes)=>{

        io.emit("message",mes)

    })

    //当用户断开连接的时候    socket.on('disconnect', function(){

        console.log('user disconnected');

    });});server.listen(3000, function(){

  console.log('listening on *:3000');});

九、利用websocket实现一个聊天室

多人聊天2、图片发送3、表情发送

var express = require('express')var app = express();//文件在服务器运行var http = require('http')var server = http.createServer(app);var path = require("path")//因为我们要做持久性通信 因此不能够用http连接 http连接与socket.io进相关联var io = require("socket.io")(server);app.use(express.static(path.join(__dirname,"./public")))var users = [];//当用户连接的时候触发的函数io.on('connection', (socket)=>{

    //监听用户连接    socket.on("system",(username,type)=>{

        if(users.includes(username)){

            socket.emit("login",0)

        }else{

            socket.userIndex = users.length;

            socket.username = username;

            users.push(username);

            io.emit("login",1,username)

        }

    })

    socket.emit("userList",users);

    socket.on("ClientsendMessage",(usename,message)=>{

        socket.broadcast.emit("serverSendMessage",usename,message)

    })

    socket.on("sendImg",(username,base64Img)=>{

        socket.broadcast.emit("serverSendImg",usename,base64Img)

    })});server.listen(3000, function(){

  console.log('listening on *:3000');});<!doctype html><html><head>

    <title>Socket.IO chat</title>

    <link rel="stylesheet" href="./css/iconfont/iconfont.css">

    <style>

        * { margin: 0; padding: 0; box-sizing: border-box; }

        ul,li{ list-style: none; }

        html, body { font: 13px Helvetica, Arial; height: 100%; }

        form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }

        form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }

        form button {  width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }

        #messages { list-style-type: none; margin: 0; padding: 0; }

        #messages li { padding: 5px 10px; }

        #messages li:nth-child(odd) { background: #eee; }

        #action { width: 100%; height: 30px; display: flex; align-items: center; }

        #action input[type='color'] { width: 40px; height: 30px; }

        #upload, #fontColor { width: 40px; height: 30px; position: relative; }

        #action input[type='file'],

        #fontColor input[type="color"] { width: 40px; height: 30px; position: absolute; left: 0%; top: 0; opacity: 0; z-index: 5;}

        #action i, #fontColor i { width: 100%; height: 100%; position: absolute; left: 0; top: 0; color: #fff; font-size: 20px;}

        #mask {  width: 100%; height: 100%; background: rgba(0, 0, 0, .3); position: absolute; z-index: 10;}

        #content{ width: 100%; height: 100%; display: flex; justify-content:space-between;}

        #content ul:nth-child(2){ width:200px; height: 100%; border-left:1px solid #ccc; }

        #userList { overflow: scroll; }

        #userList li{ line-height: 30px; border-bottom: 1px solid #bbb; width:100%; }

        .userDate{ color: green; line-height: 20px; font-size:18px; }

        .userInfo{ color: #000; line-height: 20px; font-size:14px; }

        #messages>div{ min-height: 60px; }

        #system{ color: #c33; font-size:18px; }

    </style></head><body>

    <div id="mask"></div>

    <div id="content">

        <ul id="messages"></ul>

        <ul id="userList">

            <li>用户列表</li>

        </ul>

    </div>

    <form id="form">

        <div id="action">

            <div id="fontColor">

                <input type="color">

                <class="iconfont">&#xec85;</i>

            </div>

            <div id="upload">

                <input type="file" id="file">

                <class="iconfont">&#xe674;</i>

            </div>

            <ul></ul>

        </div>

        <input id="m" autocomplete="off" />

        <input type="submit" value="提交">

    </form></body></html><script src="/socket.io/socket.io.js"></script><script src="https://code.jquery.com/jquery-1.11.1.js"></script><script src="./js/index.js"></script>

index.js

class SocketAlley {

    constructor() {

        this.mask = $("#mask");

        this.userListEl = $("#userList");

        this.messages = $("#messages");

        this.socket = io();

        this.init();

    }

    init() {

        if (!sessionStorage.getItem("status")) {

            this.username = window.prompt("请输入您的姓名");

            if (this.username) {

                sessionStorage.setItem("status", this.username);

                //当用户连接进来的时候通知服务器                this.socket.emit("system", this.username, "login")

                //检测是否连接成功                this.socket.on("login", (data, username) => {

                    if (data == 1) {

                        alert("连接成功");

                        this.mask.hide();

                        //全局通知                        var div = $("<div></div>");

                        var str = username + "进入聊天室"

                        div.text(str);

                        this.messages.append(div);

                    } else {

                        alert("用户名重复请求重新编写");

                    }

                })

            }

        } else {

            this.mask.hide();

            this.username = sessionStorage.getItem("status");

            this.socket.on("login", (data, username) => {

                //全局通知                var div = $("<div></div>");

                var str = username + "进入聊天室"

                div.text(str);

                this.messages.append(div);

            })

        }

        this.userList();

        this.serverMessage();

        this.userSendInfo();

        this.sendImg();

    }

    userList() {

        this.socket.on("userList", this.handleUserListSucc.bind(this))

    }

    handleUserListSucc(data) {

        data.forEach(this.handleUserListEach.bind(this))

    }

    handleUserListEach(item) {

        var li = $("<li></li>");

        li.text(item);

        this.userListEl.append(li);

    }

    userSendInfo() {

        $("#form").on("submit", this.handleUserSendInfo.bind(this))

    }

    handleUserSendInfo(e) {

        e.preventDefault();

        var val = $("#m").val();

        this.infoStyle(this.username, val);

        //向服务端发送消息        this.socket.emit("ClientsendMessage", this.username, val);

    }

    serverMessage() {

        this.socket.on("serverSendMessage", (username, message) => {

            this.infoStyle(username, message);

        })

        this.socket.on("serverSendImg", (username, message) => {

            this.infoImg(username, message);

        })

    }

    infoImg(username, message) {

        var parentDiv = $("<div></div>");

        var childDiv = $("<div></div>");

        var contentDiv = $("<div></div>");

        var d = new Date();

        if (/(\d{2}:\d{2}:\d{2})/.test(d)) {

            childDiv.text(username + RegExp.$1);

            var img = $("<img/>");

            img.attr("src",message);

            contentDiv.append(img);

            parentDiv.append(childDiv);

            parentDiv.append(contentDiv)

            this.messages.append(parentDiv);

            parentDiv[0].scrollIntoView();

        }

    }

    infoStyle(username, message) {

        var parentDiv = $("<div></div>");

        var childDiv = $("<div></div>");

        var contentDiv = $("<div></div>");

        var d = new Date();

        if (/(\d{2}:\d{2}:\d{2})/.test(d)) {

            childDiv.text(username + RegExp.$1);

            contentDiv.text(message);

            parentDiv.append(childDiv);

            parentDiv.append(contentDiv)

            this.messages.append(parentDiv);

            parentDiv[0].scrollIntoView();

        }

    }

    sendImg() {

        $("#file").on("change", this.sendImgCb.bind(this))

    }

    sendImgCb() {

        var _this = this;

        //只能从原生JS中拿到file对象        var file = $("#file")[0].files[0];

        //将file对象转换dataurl(base64的文件形式)        var fileReader = new FileReader()

        fileReader.onload = function (e) {

            _this.socket.emit("sendImg", _this.username, e.target.result);

            _this.infoImg(_this.username, e.target.result)

        }

        //将file转换成dataUrl的形式        fileReader.readAsDataURL(file);

    }}new SocketAlley();

十、利用socket实现一个简单版的多人点餐功能

const express = require("express");const app = express();const http = require("http");const server = http.createServer(app);const io = require("socket.io")(server);const path = require("path");app.use(express.static(path.join(__dirname, "./public")))io.on("connection", (socket) => {

    socket.on('add', (data) => {

        socket.broadcast.emit("serverAdd",data);

    })

    socket.on('reducer', (data) => {

        socket.broadcast.emit("serverReducer",data);

    })})server.listen(9000)<!DOCTYPE html><html lang="en"><head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>Document</title>

    <link rel="stylesheet" href="./css/reset.css">

    <style>

        #goodsList {

            width: 100%;

            height: 100%;

            padding: .1rem;

        }

        .goodsItem {

            display: flex;

            width: 100%;

            padding: .2rem;

        }

        .goodsItem>div:nth-child(1) {

            margin-right: .2rem;

        }

        .goodsItem img {

            width: 2rem;

            height: 2.5rem;

        }

        .goodsDes {

            flex: 1;

            display: flex;

            justify-content: space-between;

            flex-direction: column;

        }

        .goodsDes>div:nth-child(3) {

            display: flex;

        }

        .goodsDes>div:nth-child(3) .reducer {

            width: 30px;

            height: 30px;

            text-align: center;

            line-height: 30px;

            background: #ccc;

            color: #fff;

            font-size: 16px;

        }

        .goodsDes>div:nth-child(3) .add {

            width: 30px;

            height: 30px;

            text-align: center;

            line-height: 30px;

            background: #ccc;

            color: #fff;

            font-size: 16px;

        }

        .goodsDes>div:nth-child(3) input {

            width: 80px;

            height: 30px;

            border: 0;

        }

    </style></head><body>

    <!-- 

    1、需求评审

    2、(需求肯定出来了)前后端开会->定义接口(后端为主 前端为辅) 你写代码的速度 * 需求的难易程度 * 1.5 = 模块开发的时间 cnpm install json-server -g json-server中的增删改查 查:GET 增:POST 删:delete

    改:patch -->

    <div id="goodsList">

    </div></body></html><script src="/socket.io/socket.io.js"></script><script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script><script>

    class Goods {

        constructor() {

            this.socket = io();

        }

        init() {

            this.getGoods();

            this.watchServer();

        }

        getGoods() {

            $.ajax({

                type: "get",

                url: "http://localhost:3000/data",

                success: this.handleGetGoodsSucc.bind(this)

            })

        }

        handleGetGoodsSucc(data) {

            var str = "";

            for (var i = 0; i < data.length; i++) {

                str += `<div data-id="${data[i].id}">            <div>                <img src="${data[i].goodsPic}" >            </div>            <div>                <div>${data[i].goodsName}</div>                <div>单价:<span data-price="${data[i].price}">${data[i].price}</span>$</div>                <div>                    <div>-</div>                    <input type="text" value="${data[i].num}">                    <div>+</div>                </div>            </div>        </div>                `

            }

            $("#goodsList").html(str);

            this.add();

            this.reducer();

        }

        add() {

            $(".add").each(this.handleAddEach.bind(this))

        }

        handleAddEach(index) {

            $(".add").eq(index).on("click", this.handleAddCb.bind(this, index))

        }

        handleAddCb(index) {

            var n = $(".add").eq(index).prev().attr("value");

            var id = $(".add").eq(index).parent().parent().parent().attr("data-id");

            n++;

            $(".add").eq(index).prev().attr("value", n);

            var price = $(".add").eq(index).parent().parent().find("div").eq(1).find("span").attr("data-price");

            $(".add").eq(index).parent().parent().find("div").eq(1).find("span").text(price * n)

            //socket部分            this.socket.emit("add", { id: id, num: n });

        }

        reducer() {

            $(".reducer").each(this.handleReducerEach.bind(this))

        }

        handleReducerEach(index) {

            $(".reducer").eq(index).on("click", this.handleReducerCb.bind(this, index))

        }

        handleReducerCb(index) {

            var n = $(".reducer").eq(index).next().attr("value");

            var id = $(".reducer").eq(index).parent().parent().parent().attr("data-id");

            if (n == 1) {

                n = 1;

            } else {

                --n;

                this.socket.emit("reducer", { id: id, num: n });

            }

            $(".reducer").eq(index).next().attr("value", n);

            var price = $(".reducer").eq(index).parent().parent().find("div").eq(1).find("span").attr("data-price");

            $(".reducer").eq(index).parent().parent().find("div").eq(1).find("span").text(price * n)

        }

        watchServer() {

            this.socket.on("serverAdd", this.handleServerAddSucc.bind(this));

            this.socket.on("serverReducer", this.handleServerReducerSucc.bind(this))

        }

        handleServerAddSucc(data) {

            $(".add").each(this.handleAddEachServer.bind(this, data))

        }

        handleAddEachServer(data, index) {

            var id = $(".add").eq(index).parent().parent().parent().attr("data-id");

            if (id == data.id) {

                var val = $(".add").eq(index).prev().val();

                $(".add").eq(index).prev().val(Number(data.num));

            }

        }

        handleServerReducerSucc(data) {

            $(".reducer").each(this.handleReducerEachServer.bind(this, data))

        }

        handleReducerEachServer(data, index) {

            var id = $(".reducer").eq(index).parent().parent().parent().attr("data-id");

            if (id == data.id) {

                var val = $(".reducer").eq(index).next().val();

                $(".reducer").eq(index).next().val(Number(data.num));

            }

        }

    }

    new Goods().init();</script>

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯