溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

?好程序員web前端培訓(xùn)分享node學(xué)習(xí)筆記系列之四十一

發(fā)布時(shí)間:2020-08-11 05:44:14 來(lái)源:ITPUB博客 閱讀:155 作者:好程序員 欄目:web開(kāi)發(fā)

好程序員 web前端培訓(xùn)分享 node學(xué)習(xí)筆記 系列之 四十一

一、手動(dòng)封裝body-parser中間件 cookie-parser中間件

1、封裝axios請(qǐng)求方式

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的作用以及實(shí)現(xiàn)

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

     //將所有注冊(cè)的事件添加到routesMap中去      var   routesMap   =   {

         get :   {

         },

         post :   {

         }

     }

     //app這個(gè)函數(shù)中做的執(zhí)行      var   app   =   function   (req,   res)   {

         //獲取用戶(hù)請(qǐng)求的路徑          var   pathname   =   url.parse(req.url).pathname;

         //獲取用戶(hù)請(qǐng)求的方式          var   method   =   req.method.toLowerCase();

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

             //next函數(shù)用來(lái)執(zhí)行下一個(gè)中間件              var   next   =   function   ()   {

                 var   handle;

                 //執(zhí)行是沒(méi)有路徑的函數(shù)                  while   (handle   =   routesMap.all.shift())   {

                     handle(req,   res,   next)

                 }

             }

             next();

             //執(zhí)行app.use帶路徑的函數(shù)                for   ( var   key   in   routesMap)   {

                 //判斷路徑是否與用戶(hù)請(qǐng)求的路徑相同                  if   (key   ===   pathname)   {

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

                     break ;

                 }

             }

             //判斷用戶(hù)是否是get請(qǐng)求              if   (method   ==   "get" )   {

                 //如果是get請(qǐng)求則找到get請(qǐng)求相對(duì)應(yīng)得路徑 執(zhí)行對(duì)應(yīng)的函數(shù)                  for   ( var   key   in   routesMap.get)   {

                     if   (key   ==   pathname)   {

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

                         break ;

                     }

                 }

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

             }

         }

     }

     //注冊(cè)事件      app.use   =   function   ()   {

         //判斷use中的第一個(gè)參數(shù)是路徑還是一個(gè)函數(shù)          if   ( typeof   arguments[ 0 ]   ===   "string" )   {

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

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

             //建議all這個(gè)key值寫(xiě)成Symbol              if   ( ! routesMap.all)   {

                 routesMap.all   =   [];

             }

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

         }

     }

     //注冊(cè)事件      app.get   =   function   (path,   callback)   {

         routesMap.get[path]   =   callback;

     }

     //創(chuàng)建服務(wù)      app.listen   =   function   (port,   callback)   {

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

     }

     return   app;} //靜態(tài)資源訪(fǎng)問(wèn) 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的基本使用

<% … %> 開(kāi)始符和結(jié)束符之間寫(xiě)js代碼 <%= … %>輸出變量數(shù)據(jù) 變量若包含 '<' '>' '&'等字符 會(huì)被轉(zhuǎn)義 <%- … %>輸出變量(html的解析前面需要加-) 不轉(zhuǎn)義 <%- include('user/show') %>引入其他模板   包含 ./user/show.ejs <%# some comments %>來(lái)注釋?zhuān)粓?zhí)行不輸出 <%% 轉(zhuǎn)義為 '<%'<% ... -%> 刪除新的空白行模式? <%_ … _%> 刪除空白符模式開(kāi)始符和結(jié)束符內(nèi)部不可以嵌套

四、前端渲染和后端渲染的區(qū)別

后端渲染HTML的情況下,瀏覽器會(huì)直接接收到經(jīng)過(guò)服務(wù)器計(jì)算之后的呈現(xiàn)給用戶(hù)的最終的HTML字符串,這里的計(jì)算就是服務(wù)器經(jīng)過(guò)解析存放在服務(wù)器端的模板文件來(lái)完成的,在這種情況下,瀏覽器只進(jìn)行了HTML的解析,以及通過(guò)操作系統(tǒng)提供的操縱顯示器顯示內(nèi)容的系統(tǒng)調(diào)用在顯示器上把HTML所代表的圖像顯示給用戶(hù)。 前端渲染就是指瀏覽器會(huì)從后端得到一些信息,這些信息或許是適用于題主所說(shuō)的angularjs的模板文件,亦或是JSON等各種數(shù)據(jù)交換格式所包裝的數(shù)據(jù),甚至是直接的合法的HTML字符串。這些形式都不重要,重要的是,將這些信息組織排列形成最終可讀的HTML字符串是由瀏覽器來(lái)完成的,在形成了HTML字符串之后,再進(jìn)行顯示

五、用所學(xué)的express生成器+ejs做一個(gè)簡(jiǎn)單的列表頁(yè)

、socket的基本使用

1、什么是socket?

網(wǎng)絡(luò)上兩個(gè)程序通過(guò)一個(gè)雙向的通信連接實(shí)現(xiàn)數(shù)據(jù)交換,這個(gè)連接的一端稱(chēng)為socket

2、http請(qǐng)求與socket的區(qū)別

1、在以前我們實(shí)現(xiàn)數(shù)據(jù)交換已經(jīng)有了HTTP協(xié)議,為什么還要學(xué)習(xí)socket? 回顧:當(dāng)輸出 www.baidu.com 的時(shí)候?yàn)g覽器執(zhí)行了那些操作? 2、http通信的 特點(diǎn): 1、連接屬于非持久性連接:TCP的三次握手 2、客戶(hù)端只能訪(fǎng)問(wèn)服務(wù)端,服務(wù)端無(wú)法訪(fǎng)問(wèn)客戶(hù)端,屬于單項(xiàng)通信 TCP三次握手: TCP三次握手過(guò)程中不傳遞數(shù)據(jù),只為同步連接雙方的序列號(hào)和確認(rèn)號(hào)傳遞數(shù)據(jù),在握手后服務(wù)端和客戶(hù)端才開(kāi)始傳輸數(shù)據(jù),在理想狀態(tài)下,TCP連接一旦建立,在通信的雙方中任何一方主動(dòng)斷開(kāi)連接之前TCP連接會(huì)一直保持下去。 socket通信 特點(diǎn): 1、持久性連接 2、雙向通信,客戶(hù)端能訪(fǎng)問(wèn)服務(wù)端,服務(wù)端也能訪(fǎng)問(wèn)客戶(hù)端 socket是對(duì)TCP/IP協(xié)議的封裝,socket只是一個(gè)接口而不是一個(gè)協(xié)議,通過(guò)Socket我們才能使用TCP/IP/UDP協(xié)議

3、通過(guò)node內(nèi)置模塊net實(shí)現(xiàn)簡(jiǎn)單版聊天

1、socket連接需要由2個(gè)節(jié)點(diǎn): 1)clientSocket 2)serverSocket 2、文本流:readline

const   net   =   require( "net" ); const   server   =   net.createServer(); const   clients   =   []; //當(dāng)有人連接服務(wù)端的時(shí)候回觸發(fā)當(dāng)前函數(shù) server.on( "connection" ,(client)=>{

     //給每一個(gè)用戶(hù)添加一個(gè)唯一的標(biāo)識(shí)      client.id   =   clients.length;

     clients.push(client);

     //將客戶(hù)端的消息轉(zhuǎn)發(fā)給所有的用戶(hù)      client.on( "data" ,(data)=>{

         clients.forEach(item=>{

             //判斷用戶(hù)是否存在              if (item)   item.write( "服務(wù)端:" + data);

         })

     })

     //判斷用戶(hù)是否退出群聊      client.on( "close" ,()=>{

         clients[client.id]   =   null ;     

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

     input :   process.stdin,

     output :   process.stdout}) //客戶(hù)端連接服務(wù)端 client.connect( 9000 ,   ()   =>   {

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

         console.log(data.toString());

     })}) //獲取終端的內(nèi)容將內(nèi)容轉(zhuǎn)發(fā)到服務(wù)端 rl.on( "line" ,   (val)   =>   {

     client.write(val);})

七、webSocket的基本使用

const   WebSocket   =   require( 'ws' ); //創(chuàng)建服務(wù) const   server   =   new   WebSocket.Server({   port :   9000   }); //監(jiān)控用戶(hù)連接 server.on( 'connection' ,   (client,req)=>{

    var   ip   =   req.connection.remoteAddress;

     //監(jiān)聽(tīng)客戶(hù)端傳遞到服務(wù)端的消息      client.on( 'message' ,   (data)=>{

         //將消息轉(zhuǎn)發(fā)給所有的用戶(hù)          server.clients.forEach((item)=>{

             //判斷用戶(hù)是否是連接的狀態(tài)              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" > 點(diǎn)擊 < /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" );

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

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

        li.innerText   =   e.data;

        list.appendChild(li);

        li.scrollIntoView();

     }

     //向服務(wù)端發(fā)送消息 send      btn.onclick   =   function (){

         var   val   =   txt.value;

         client.send(val);

         txt.value   =   "" ;

     } < /script>

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

var   express   =   require( 'express' ) var   app   =   express(); //文件在服務(wù)器運(yùn)行 var   http   =   require( 'http' ) var   server   =   http.createServer(app); var   path   =   require( "path" ) //因?yàn)槲覀円龀志眯酝ㄐ?因此不能夠用http連接 http連接與socket.io進(jìn)相關(guān)聯(lián) var   io   =   require( "socket.io" )(server);app.use(express. static (path.join(__dirname, "./public" ))) //當(dāng)用戶(hù)連接的時(shí)候觸發(fā)的函數(shù) io.on( 'connection' ,   (socket)=>{

     console.log( 'a user connected' );

     //接受客戶(hù)端消息 將消息轉(zhuǎn)發(fā)給所有用戶(hù)      socket.on( "sendMessage" ,(mes)=>{

         io.emit( "message" ,mes)

     })

     //當(dāng)用戶(hù)斷開(kāi)連接的時(shí)候      socket.on( 'disconnect' ,   function (){

         console.log( 'user disconnected' );

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

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

九、利用websocket實(shí)現(xiàn)一個(gè)聊天室

1、多人聊天 2、圖片發(fā)送 3、表情發(fā)送

var   express   =   require( 'express' ) var   app   =   express(); //文件在服務(wù)器運(yùn)行 var   http   =   require( 'http' ) var   server   =   http.createServer(app); var   path   =   require( "path" ) //因?yàn)槲覀円龀志眯酝ㄐ?因此不能夠用http連接 http連接與socket.io進(jìn)相關(guān)聯(lián) var   io   =   require( "socket.io" )(server);app.use(express. static (path.join(__dirname, "./public" ))) var   users   =   []; //當(dāng)用戶(hù)連接的時(shí)候觸發(fā)的函數(shù) io.on( 'connection' ,   (socket)=>{

     //監(jiān)聽(tīng)用戶(hù)連接      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 :   13 px   Helvetica,   Arial;   height :   100 % ;   }

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

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

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

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

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

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

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

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

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

         # action   input[type = 'file' ],

         # fontColor   input[type = "color" ]   {   width :   40 px;   height :   30 px;   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 :   20 px;}

         # 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 : 200 px;   height :   100 % ;   border - left : 1 px   solid   # ccc;   }

         # userList   {   overflow :   scroll;   }

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

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

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

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

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

     < /style> < /head> < body >

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

     < div   id = "content" >

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

         < ul   id = "userList" >

             < li > 用戶(hù)列表 < /li>

         < /ul>

     < /div>

     < form   id = "form" >

         < div   id = "action" >

             < div   id = "fontColor" >

                 < input   type = "color" >

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

             < /div>

             < div   id = "upload" >

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

                 < i   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( "請(qǐng)輸入您的姓名" );

             if   ( this .username)   {

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

                 //當(dāng)用戶(hù)連接進(jìn)來(lái)的時(shí)候通知服務(wù)器                  this .socket.emit( "system" ,   this .username,   "login" )

                 //檢測(cè)是否連接成功                  this .socket.on( "login" ,   (data,   username)   =>   {

                     if   (data   ==   1 )   {

                         alert( "連接成功" );

                         this .mask.hide();

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

                         var   str   =   username   +   "進(jìn)入聊天室"

                         div.text(str);

                         this .messages.append(div);

                     }   else   {

                         alert( "用戶(hù)名重復(fù)請(qǐng)求重新編寫(xiě)" );

                     }

                 })

             }

         }   else   {

             this .mask.hide();

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

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

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

                 var   str   =   username   +   "進(jìn)入聊天室"

                 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);

         //向服務(wù)端發(fā)送消息          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對(duì)象          var   file   =   $( "#file" )[ 0 ].files[ 0 ];

         //將file對(duì)象轉(zhuǎn)換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轉(zhuǎn)換成dataUrl的形式          fileReader.readAsDataURL(file);

     }} new   SocketAlley();

十、利用socket實(shí)現(xiàn)一個(gè)簡(jiǎn)單版的多人點(diǎn)餐功能

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 :   .1 rem;

         }

         .goodsItem   {

             display :   flex;

             width :   100 % ;

             padding :   .2 rem;

         }

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

             margin - right :   .2 rem;

         }

         .goodsItem   img   {

             width :   2 rem;

             height :   2.5 rem;

         }

         .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 :   30 px;

             height :   30 px;

             text - align :   center;

             line - height :   30 px;

             background :   # ccc;

             color :   # fff;

             font - size :   16 px;

         }

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

             width :   30 px;

             height :   30 px;

             text - align :   center;

             line - height :   30 px;

             background :   # ccc;

             color :   # fff;

             font - size :   16 px;

         }

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

             width :   80 px;

             height :   30 px;

             border :   0 ;

         }

     < /style> < /head> < body >

     <!--  

     1 、 需求評(píng)審

     2 、 (需求肯定出來(lái)了)前后端開(kāi)會(huì) -> 定義接口(后端為主   前端為輔)   你寫(xiě)代碼的速度   *   需求的難易程度   *   1.5   =   模塊開(kāi)發(fā)的時(shí)間   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>單價(jià):<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>

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI