国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

手把手教你擼一個(gè)網(wǎng)頁(yè)聊天室

leiyi / 5389人閱讀

摘要:前端邏輯搞定之后,思考一下這個(gè)聊天室的交互是怎么實(shí)現(xiàn)的。在前端監(jiān)聽(tīng)一個(gè)事件,這個(gè)事件的觸發(fā)條件是成功和服務(wù)端建立連接。攜帶一個(gè)參數(shù),即用戶的輸入。別人發(fā)送的消息現(xiàn)在就需要在前端建立一個(gè)響應(yīng)服務(wù)端有新消息的監(jiān)聽(tīng)事件了。

一些廢話:)

最近在學(xué)校比較閑,終于有這么一塊時(shí)間可以自由支配了,所以內(nèi)心還是十分的酸爽舒暢的。當(dāng)然了,罪惡的事情也是有的,比如已經(jīng)連續(xù)一周沒(méi)有吃早飯了,其實(shí)現(xiàn)在回頭想想,真的不能怪我啊,因?yàn)樽罱奶鞖鈱?shí)在是太!冷!了!好吧為了減少賴床的罪惡感,還是學(xué)(gǎo)點(diǎn)(diǎn)東(shì)西(qing)好了。不說(shuō)廢話了,還是進(jìn)入正題。

進(jìn)入正題

這個(gè)丑陋無(wú)比的聊天室,暫時(shí)給他后面加個(gè)“v1.0”吧,畢竟也是沒(méi)有經(jīng)過(guò)什么迭代,寫(xiě)好就直接放出來(lái)了,當(dāng)然也有很多可以再搞搞的地方,比如:

[ ] 支持發(fā)送圖片

[ ] 支持發(fā)送表情

[ ] 顯示在線用戶名單

其實(shí)這里還是有很多想象空間的,不是重點(diǎn)也就不展開(kāi)說(shuō)了。
在寫(xiě)這個(gè)demo的時(shí)候,我是邊學(xué)邊寫(xiě)的狀態(tài),學(xué)習(xí)資料以劉哇勇大神的Node.js+Web Socket 打造即時(shí)聊天程序嗨聊為主,主流搜索引擎和我最喜歡的技術(shù)社區(qū)SegmentFault為輔。

源碼

源碼已經(jīng)上傳至我的github, clone到本地以后在terminal中運(yùn)行下面兩條命令:

npm install
node server

然后打開(kāi)瀏覽器,訪問(wèn)localhost,就可以在不聯(lián)網(wǎng)的情況下看到這個(gè)demo啦。

預(yù)覽

輸入用戶名完成登陸

然后就可以開(kāi)始和在線的人聊天了

準(zhǔn)備工作

當(dāng)然啦,Node.js是必不可少的,這里推薦兩個(gè)很棒的Node.js教程:

Node入門(mén)

Node.js包教不包會(huì)

Node.js可以實(shí)現(xiàn)用短短的幾行代碼就起一個(gè)服務(wù)器

var http = require("http");
http.createServer(function(request, response){
    response.writeHead(200, {"Content-type":"text/plain"});
    response.write("Hey you, my name is kyrieliu~");
    response.end();
}).listen(8080);

當(dāng)你在Terminal執(zhí)行這段代碼以后,訪問(wèn)http://localhost/:8080,就可以看到一行字:Hey you, my name is kyrieliu~
這就代表你的node服務(wù)已經(jīng)架起來(lái)了,阿西,js寫(xiě)后臺(tái)邏輯,用腳指頭想想都會(huì)覺(jué)得是一件很酷的事情呢

另外,還用到了兩個(gè)包模塊:

express

socket.io

express是node.js中管理路由響應(yīng)請(qǐng)求的模塊,根據(jù)請(qǐng)求的URL返回相應(yīng)的HTML頁(yè)面。這里我們使用一個(gè)事先寫(xiě)好的靜態(tài)頁(yè)面返回給客戶端,只需使用express指定要返回的頁(yè)面的路徑即可。如果不用這個(gè)包,我們需要將HTML代碼與后臺(tái)JavaScript代碼寫(xiě)在一起進(jìn)行請(qǐng)求的響應(yīng),不太方便。

socket.io封裝了websocket,同時(shí)包含了其它的連接方式,比如Ajax。原因在于不是所有的瀏覽器都支持websocket,通過(guò)socket.io的封裝,你不用關(guān)心里面用了什么連接方式。你在任何瀏覽器里都可以使用socket.io來(lái)建立異步的連接。

UI

界面就像第一眼看到的那樣簡(jiǎn)(chǒu)單(lòu),不過(guò)“麻雀雖小,五臟俱全”,該有的東西還是得有,這里就直接貼DOM結(jié)構(gòu)。

    

直接看注釋?zhuān)湍芮逦目吹竭@只小麻雀的“心”、“肝”、“脾”、“肺”四個(gè)部分。(“腎”呢?哼,你以為我的新手機(jī)怎么來(lái)的?)
至于那些辣眼睛的類(lèi)名,是因?yàn)轫?xiàng)目里用到了Bootstrap,也算是偷了個(gè)懶。

前端邏輯

UI搞定之后,思考一下這個(gè)聊天室的交互是怎么實(shí)現(xiàn)的。
“你前面不是說(shuō)了,用websocket嘛?!?
此話不假,不過(guò)這里我指的是交互,畢竟你寫(xiě)一個(gè)程序的話,對(duì)程序內(nèi)的邏輯必須做到“吹毛求疵”(我這個(gè)成語(yǔ)用對(duì)了沒(méi))

與服務(wù)端建立連接

輸入昵稱(chēng)完成登錄

發(fā)送消息

接受消息

仔細(xì)想想好像大概就這么多了,那就開(kāi)始逐一攻破

與服務(wù)端建立連接

這里要注意,因?yàn)槭且粋€(gè)聊天系統(tǒng),所以與服務(wù)端建立連接的方式不同于往常,這里用到的協(xié)議是HTTP WebSocket,從而實(shí)現(xiàn)持久連接。
簡(jiǎn)單的解釋一下,這里的“持久”,是相對(duì)于HTTP這種“非持久”的協(xié)議來(lái)說(shuō)的(閣下的意思是,HTTP的夫人會(huì)很羨慕WebSocket的夫人咯)。
通過(guò)閱讀Ovear在知乎上的回答,大致說(shuō)一下這兩個(gè)協(xié)議之間的區(qū)別。

HTTP

HTTP的生命周期大概是這樣的,一個(gè)request,一個(gè)response,這次請(qǐng)求就結(jié)束了;HTTP 1.1中進(jìn)行了改進(jìn),增加了一個(gè)keep-alive,效果是在這次HTTP連接中,可以發(fā)送多個(gè)request,接受多個(gè)response,但本質(zhì)上,request = response,也就是說(shuō),請(qǐng)求和響應(yīng)永遠(yuǎn)是一一對(duì)應(yīng)的,沒(méi)有request時(shí),服務(wù)端不能主動(dòng)response。

WebSocket

當(dāng)客戶端與服務(wù)端完成協(xié)議升級(jí)以后(HTTP -> WebSocket),就建立了一個(gè)持久連接,有多持久呢?這個(gè)連接可以持續(xù)存在知道客戶端或服務(wù)端某一方主動(dòng)的關(guān)閉連接。與HTTP最大的不同是,此時(shí)的服務(wù)端可以主動(dòng)推送消息給客戶端咯。在這個(gè)項(xiàng)目中,我們用socket.io這個(gè)包模塊來(lái)實(shí)現(xiàn)WebSocket,socket.io不僅實(shí)現(xiàn)了對(duì)WebSocket的封裝,還將連同Ajax輪詢和其他實(shí)時(shí)通信方式封裝成了通用的接口,這么做的原因是,當(dāng)服務(wù)器不支持WebSocket時(shí),可以轉(zhuǎn)換為其他的實(shí)現(xiàn)方式,嘖嘖嘖,堪稱(chēng)縱享絲滑

接下來(lái)就是實(shí)現(xiàn)的部分,前端在引入了socket.io.js這個(gè)文件以后應(yīng)該怎么做呢?
Talk is cheap, show you the CODE.

var socket = io.connect();

對(duì),就是這么簡(jiǎn)單,不信你去看官方文檔。

輸入昵稱(chēng)完成登錄

這里的“登錄”,不是真正的登錄,當(dāng)執(zhí)行完 io.connect() 之后,這個(gè)連接就算已經(jīng)建立了,這里是在處理一些交互上的行為。
在前端監(jiān)聽(tīng)一個(gè)connect事件,這個(gè)事件的觸發(fā)條件是:成功和服務(wù)端建立連接。

socket.on("connect",function(){
    //do something
});

回調(diào)里面是此時(shí)要完成的DOM操作,比如:

改變提示文字(初始是“Connecting to server......”)

顯示遮蓋層

聚焦文本框

當(dāng)用戶輸入自己的昵稱(chēng)點(diǎn)擊登錄按鈕后,當(dāng)前socket觸發(fā)一個(gè)login事件到服務(wù)端:

socket.emit("login",nickname);

攜帶一個(gè)參數(shù),這個(gè)參數(shù)就是用戶輸入的昵稱(chēng)。
當(dāng)服務(wù)端對(duì)這個(gè)昵稱(chēng)進(jìn)行合法性檢測(cè),通過(guò)時(shí)觸發(fā):

socket.on("loginSuccess", function(){
    //1. 隱藏登錄層
    //2. 用戶可以愉快和別人聊天了~
});

如果用戶輸入的昵稱(chēng)不合法,則觸發(fā):

socket.on("loginFailed", function(){
    //1. 提示用戶昵稱(chēng)哪里出問(wèn)題了
    //2. 等待用戶重新輸入
});

注意這里的事件名稱(chēng),如login、loginSuccess、loginFailed都是自定義的,只要保證和服務(wù)端的一致就ok了。

發(fā)送消息

想像一下用戶發(fā)送消息這個(gè)動(dòng)作,分解一下:輸入文本 -> 點(diǎn)擊發(fā)送。也就是這倆了,ok,這里需要給發(fā)送按鈕掛上一個(gè)事件,告訴服務(wù)端,“服務(wù)端服務(wù)端,這里是socket XXX,我給你發(fā)了一個(gè)消息哦,注意查收,over?!?/p>

socket.emit("msgSend",msg);

攜帶一個(gè)參數(shù),即用戶的輸入。

接受消息

接受消息這個(gè)邏輯有三種情況

自己發(fā)送的消息

別人發(fā)送的消息

系統(tǒng)的提示信息

莫慌,一個(gè)一個(gè)來(lái)看。

自己發(fā)送的消息

自己發(fā)送的消息直接顯示在聊天消息的面板,接收自己發(fā)送的消息不用和后臺(tái)交互,只需要告訴后臺(tái)我給大家發(fā)了這條消息即可。當(dāng)然啦,你也可以仿照微信對(duì)自己發(fā)送的消息進(jìn)行處理:發(fā)送的瞬間將自己的消息添加聊天面板 -> 給旁邊放個(gè)小菊花或者loading的字樣 -> 與后臺(tái)進(jìn)行交互 -> 成功則隱藏小菊花;失敗則將小菊花變成紅色感嘆號(hào)暗示用戶發(fā)送失敗。

別人發(fā)送的消息

現(xiàn)在就需要在前端建立一個(gè)響應(yīng)服務(wù)端“有新消息”的監(jiān)聽(tīng)事件了。

socket.on("newMsg", function(nickname, msg){
    //顯示這條新消息
});

回調(diào)函數(shù)里面有兩個(gè)參數(shù),nickname和msg,分別是消息發(fā)送者的昵稱(chēng)和消息內(nèi)容,這倆是怎么來(lái)的呢?不要急,后面會(huì)在服務(wù)端邏輯里面講到,這里你只需要知道,在前端接受新消息的時(shí)候,因?yàn)闋砍兜秸故拘孪?,所以需要這兩個(gè)參數(shù)。

系統(tǒng)的提示信息

關(guān)于系統(tǒng)的提示信息,主要分為兩個(gè):

提示新加入和退出的用戶

展示當(dāng)前在線的用戶數(shù)




大概是這個(gè)樣子,所以需要在前端對(duì)系統(tǒng)事件進(jìn)行監(jiān)聽(tīng)

socket.on("system", function(nickname, count, type){
    //1.根據(jù)系統(tǒng)事件類(lèi)型(新加入或離開(kāi))來(lái)提示用戶
    //2.修改在線用戶數(shù)量
});

這里的三個(gè)參數(shù)也都是必不可少的,nickname代表觸發(fā)系統(tǒng)事件的用戶的昵稱(chēng),count表示當(dāng)前在線的用戶數(shù)量,type表示事件類(lèi)型(加入/離開(kāi))。同樣,這三個(gè)參數(shù)也都是服務(wù)端傳過(guò)來(lái)的。

后臺(tái)邏輯

與前端對(duì)應(yīng),后臺(tái)的邏輯主要分為以下幾個(gè)部分

起服務(wù)

建立連接

用戶登錄

接受用戶發(fā)送的消息并廣播之

系統(tǒng)消息的處理

起服務(wù)
var express = require("express");
var app = express();
var server = require("http").createServer(app);
var io = require("socket.io")(server);

app.use("/",express.static(__dirname + "/www"));
server.listen(8080);

因?yàn)槲野亚岸宋募?html/js/css)放到了www這個(gè)文件夾內(nèi),所以用express指定返回給瀏覽器的頁(yè)面路徑現(xiàn)在這樣。
當(dāng)然,除了express以外,也要引入socket.io模塊并綁定到服務(wù)器。

建立連接

服務(wù)起好了,怎么建立連接呢?

io.on("connection", function(socket){
    //do something
});

就...這樣...?
昂。


你沒(méi)有看錯(cuò),我也沒(méi)有寫(xiě)錯(cuò),這里對(duì)應(yīng)前端邏輯的:

var socket = io.connect();
socket.on("connect", function(){
    //do something
});

連接建立了以后,所有關(guān)于socket活動(dòng)的邏輯就可以開(kāi)始寫(xiě)了。(FYI:當(dāng)然,是寫(xiě)在這個(gè)connection事件的回調(diào)里面)

用戶登錄

還記得前端觸發(fā)的登錄事件叫什么嘛

socket.emit("login", nickname);

叫l(wèi)ogin,而且還攜帶了一個(gè)參數(shù)——用戶想給自己起的昵稱(chēng)nickname。好,我們來(lái)寫(xiě)對(duì)應(yīng)的后臺(tái)邏輯

socket.on("login", function(nickname){
    //do something
});

這里的do something要做什么呢?即對(duì)用戶輸入的昵稱(chēng)進(jìn)行合法性校驗(yàn),比如是否已經(jīng)存在、長(zhǎng)度限制、符號(hào)限制等。
球都麻袋,好像有哪里不對(duì)...


長(zhǎng)度限制和符號(hào)限制?這倆哥們根本就不用放在服務(wù)器上做嘛,直接在前端就搞了。所以我們的問(wèn)題只剩一個(gè)了——昵稱(chēng)的唯一性。
既然要檢測(cè)昵稱(chēng)是否唯一,首先得有一個(gè)當(dāng)前在線用戶昵稱(chēng)的總集,不然去哪里檢測(cè)昵稱(chēng)是否存在嘞?


所以要在全局維護(hù)一個(gè)數(shù)組,保存當(dāng)前在線用戶的昵稱(chēng)

var users = [];

在這個(gè)數(shù)組里找用戶通過(guò)login事件傳過(guò)來(lái)的nickname,如果不存在,說(shuō)明當(dāng)前昵稱(chēng)合法,用戶可以叫這個(gè)名字,那么

socket.nickname = nickname;//記錄下當(dāng)前socket的nickname
users.push(nickname);
socket.emit("loginSuccess");//觸發(fā)loginSuccess事件

如果昵稱(chēng)已經(jīng)存在了,就觸發(fā)一登錄失敗事件,前端再做相應(yīng)的交互即可。

socket.emit("loginFailed");
接收用戶發(fā)送的消息并

按照約定好的事件名來(lái)寫(xiě)服務(wù)端的監(jiān)聽(tīng)程序

socket.on("msgSend", function(msg){
    socket.broadcast.emit("newMsg", socket.nickname, msg);
});

這里調(diào)用的api是socket的廣播事件,效果是廣播消息到除了當(dāng)前socket以外的所有socket。

系統(tǒng)消息的處理

剩下的工作就是處理系統(tǒng)消息了,首先要明確有哪些系統(tǒng)消息

提示用戶加入

提示用戶離開(kāi)

更新在線用戶數(shù)

當(dāng)用戶輸入的昵稱(chēng)通過(guò)合法性校驗(yàn)以后,系統(tǒng)提示新加入的用戶

io.sockets.emit("system",nickname, users.length, "login");

io.sockets.emit()
的作用是向當(dāng)前所有socket觸發(fā)一個(gè)事件,這里要區(qū)別于socket.broadcast.emit()。
仿照上面的代碼,寫(xiě)出當(dāng)用戶離開(kāi)時(shí)的廣播事件:

io.sockets.emit("system", nickname, users.length, "logout");

但是要寫(xiě)在哪里呢?這時(shí)候,就需要在服務(wù)端額外的監(jiān)聽(tīng)一個(gè)斷開(kāi)事件

socket.on("disconnect", function(){
    var index = users.indexOf(socket.nickname);
    users.splice(index, 1);//將斷開(kāi)用戶的昵稱(chēng)從全局?jǐn)?shù)組users中刪除
    io.sockets.emit("system", socket.nickname, users.length, "logout");
});
總結(jié)

至此,一個(gè)基于Node.js的聊天室就算擼成了,當(dāng)然還有許多可以優(yōu)化的地方,不過(guò)核心功能也就這些,能看到這里的都是好漢,因?yàn)樽约簩?xiě)完看了一遍,感覺(jué)真像是老太太的裹腳布——又臭又長(zhǎng)
好啦,最后打個(gè)廣告,誒我就不說(shuō)是什么,好奇的童鞋自己掃掃看吧~

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/50255.html

相關(guān)文章

  • 把手你擼一個(gè)網(wǎng)頁(yè)天室

    摘要:前端邏輯搞定之后,思考一下這個(gè)聊天室的交互是怎么實(shí)現(xiàn)的。在前端監(jiān)聽(tīng)一個(gè)事件,這個(gè)事件的觸發(fā)條件是成功和服務(wù)端建立連接。攜帶一個(gè)參數(shù),即用戶的輸入。別人發(fā)送的消息現(xiàn)在就需要在前端建立一個(gè)響應(yīng)服務(wù)端有新消息的監(jiān)聽(tīng)事件了。 一些廢話:) 最近在學(xué)校比較閑,終于有這么一塊時(shí)間可以自由支配了,所以內(nèi)心還是十分的酸爽舒暢的。當(dāng)然了,罪惡的事情也是有的,比如已經(jīng)連續(xù)一周沒(méi)有吃早飯了,其實(shí)現(xiàn)在回頭想想...

    nemo 評(píng)論0 收藏0
  • 把手你擼一個(gè)泡妞神奇

    摘要:畫(huà)字首先我在畫(huà)布上畫(huà)了個(gè)點(diǎn),用這些點(diǎn)來(lái)組成我們要顯示的字,用不到的字就隱藏起來(lái)。星星閃爍效果這個(gè)效果實(shí)現(xiàn)很簡(jiǎn)單,就是讓星星不停的震動(dòng),具體就是讓點(diǎn)的目的地坐標(biāo)不停的進(jìn)行小范圍的偏移。 哈哈哈哈?。。‘?dāng)我說(shuō)在寫(xiě)這邊文章的時(shí)候,妹子已經(jīng)追到了,哈哈哈哈哈?。。?其實(shí)東西是一年前寫(xiě)的,妹子早就追到手了,當(dāng)時(shí)就是用這個(gè)東西來(lái)表白的咯,二話不說(shuō),先看效果(點(diǎn)擊屏幕可顯示下一句) showImg(...

    funnyZhang 評(píng)論0 收藏0
  • 把手你擼個(gè)vue2.0彈窗組件

    摘要:組件結(jié)構(gòu)同組件結(jié)構(gòu)通過(guò)方法獲取元素的大小及其相對(duì)于視口的位置,之后對(duì)提示信息進(jìn)行定位??梢杂脕?lái)進(jìn)行一些復(fù)雜帶校驗(yàn)的彈窗信息展示,也可以只用于簡(jiǎn)單信息的展示??梢酝ㄟ^(guò)屬性來(lái)顯示任意標(biāo)題,通過(guò)屬性來(lái)修改顯示區(qū)域的寬度。 手把手教你擼個(gè)vue2.0彈窗組件 在開(kāi)始之前需要了解一下開(kāi)發(fā)vue插件的前置知識(shí),推薦先看一下vue官網(wǎng)的插件介紹 預(yù)覽地址 http://haogewudi.me/k...

    mrli2016 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

leiyi

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<