您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何使用JavaScript與Node.js打造一款聊天App,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
聊天是我們人與人交流最直接的方式,互聯網的加入使我們交流更加便捷。我們手機上的微信、QQ是我們手機必不可少的應用軟件。那么,我們是否可以做一款聊天應用呢?
之前我自己閑著沒事,研究過一些技術,做了一款即時通訊應用,下面我將選取幾幅具有代表性的圖片供大家參考。
以上是這款應用的主要頁面,功能可能相對簡陋點,不過基本的功能已經實現了,下面我將給出核心代碼,全部源碼地址在文末。
前臺主要核心邏輯:
這里我只列舉了js核心代碼,查看完整代碼可以去文末。
function sock() { return io.connect("http://localhost:3003"); // http環境下 } // 心跳機制 document.addEventListener('visibilitychange', function () { if (document.visibilityState == 'hidden') { //記錄頁面隱藏時間 sock() console.log('隱藏了') } }) setInterval(() => { sock() }, 10000); var socket = sock() var re = document.querySelector("#re"); var register1 = document.querySelector(".register"); var init = document.querySelector(".init"); var passr = document.querySelector("#passr"); var passl = document.querySelector("#passl"); var login1 = document.querySelector(".login"); var register_b = document.querySelector("#register_b"); var lo = document.querySelector("#lo"); var chat = document.querySelector("#chat"); var login_b = document.querySelector("#login_b"); var myMes = ""; var vf = ""; var na = ""; var p = ""; var we = ""; var div = ""; var v = ""; var q = 0; var regCn = /[@:]/im; var pattern = /^[\u4E00-\u9FA5]{1,5}$/; // 同意 document.querySelector('.yes').onclick=function () { document.querySelector('.dark').style.display='none' } document.querySelector('.ys').onclick = function () { document.querySelector('.dark').style.display = 'block' } // 初始頁面注冊 document.querySelector("#reg").onclick = function () { register1.style.display = "block"; init.style.display = "none"; document.querySelector(".bg").style.display = "none"; } // 初始頁面登錄 document.querySelector("#log").onclick = function () { login1.style.display = "block"; init.style.display = "none"; document.querySelector(".bg").style.display = "none"; } // 登錄按鈕 login_b.onclick = function () { login(); } // 注冊按鈕 register_b.onclick = function () { register(); } //發送 document.getElementById("btn").onclick = function () { send(); }; // 內容填充 document.getElementById("text").onkeyup = function () { if (document.getElementById("text").value.length != 0) { document.getElementById("btn").style.cssText = "background:#98E165;color:#fff;" } else { document.getElementById("btn").style.cssText = "background: #DDDEE2;color:#fff" } } document.querySelector("#text").onclick = function () { document.querySelector('#text').scrollIntoView(false); } // 傳名 var users2 = ""; socket.on('users', function (users) { users2 = users; // console.log(users2); }); // 傳密碼 var pass2 = "" socket.on('pass', function (val) { pass2 = val; // console.log(pass2) }); // 統計在線人數 var arrh = [] socket.on('dataval', function (val) { vf = val; console.log(vf); for (let i = 0; i < vf.length; i++) { // uu++ arrh.push(vf[i]) console.log(arrh) } var rf = [...new Set(arrh)] console.log(rf) rf = vf for (let j = 0; j < rf.length; j++) { var li = document.createElement("li"); li.classList.add("active"); li.innerText = rf[j] console.log(rf[j]) socket.emit("time", rf[j]); document.querySelector(".fix").appendChild(li); } }); socket.on('join', function (val) { document.querySelector(".fix").innerHTML = '' }) socket.on('disconnect', function (val) { console.log('離開了') document.querySelector(".fix").innerHTML = '' }) // 生成數組 var ar = ""; socket.on('array', function (val) { ar = val; // console.log(ar); }); // 封裝注冊 function register() { if (re.value.length == 0) { sweetAlert("請輸入用戶名!"); return false; } else if (regCn.test(re.value)) { sweetAlert("格式錯誤,不能夠用和:符號取名,請重新輸入!"); return false; } else if (pattern.test(re.value)) { sweetAlert("不能使用中文字符哦!"); return false; } else if (!(re.value.length == 0 && regCn.test(re.value))) { if (users2.indexOf(re.value) != -1) { sweetAlert("已經注冊啦,換一個用戶名吧!"); } else { names(re.value.trim()); pass(passr.value.trim()); sweetAlert("注冊成功,您的用戶名:" + re.value.trim()); document.querySelector(".swal-button").onclick = function () { window.location.reload(); } } } } //移動端使用touchend var event = navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i) ? 'touchend' : 'click'; // 選擇器 var Q = function (id) { return document.getElementById(id) }; //右 var _right = new mSlider({ dom: ".layer-right", direction: "right" }); Q("btnRight").addEventListener(event, function (e) { _right.open(); }) // 封裝登錄 function login() { if (lo.value.length == 0) { sweetAlert("請輸入用戶名!"); return false; } else if (regCn.test(lo.value)) { sweetAlert("格式錯誤,不能夠用和:符號取名,請重新輸入!"); return false; } else if (pattern.test(lo.value)) { sweetAlert("不能使用中文字符哦!"); return false; } else if (!(lo.value.length == 0 && regCn.test(lo.value))) { if (users2.indexOf(lo.value) != -1) { for (var i = 0; i < users2.length; i++) { if (users2[i] === lo.value && pass2[i] === passl.value) { if (ar.indexOf(lo.value) == -1) { sweetAlert("恭喜您,登錄成功!"); socket.emit('setName', lo.value.trim()); names1(lo.value.trim()); login1.style.display = "none"; document.querySelector(".bg").style.display = "none"; document.querySelector(".cd span").style.display = "none"; document.querySelector(".title img").style.display = "block"; document.querySelector(".fix").style.display = "block"; document.querySelector(".title").style.display = "block"; _right.open(); document.querySelector(".swal-button").onclick = function () { document.getElementById("text").focus(); document.querySelector(".fix").addEventListener('click', function (e) { if (e.target.nodeName === "LI" && e.target.innerText != document.title) { _right.close(); document.querySelector(".chat_b").style.display = "block"; document.querySelector(".box").style.display = "block"; document.querySelector(".tit").innerText = e.target.innerText; document.querySelector(".ys").style.display="none"; document.querySelector("#text").focus(); onOff = true; } else { sweetAlert("不能跟自己聊天哦~"); } }) } } else { sweetAlert("不能重復登錄哦!"); return } } if (users2[i] === lo.value && pass2[i] != passl.value) { sweetAlert("密碼錯誤!"); return; } } } else { sweetAlert("請先注冊哦!"); login1.style.display = "none"; register1.style.display = "block"; } } } // 傳名 function names(value) { this.name = value; socket.emit("reg", name); } function names1(value) { this.name1 = value; socket.emit("join", name1); document.title = name1 } // 傳密碼 function pass(value) { socket.emit("pass", value); } socket.on("join", function (user) { this.na = user; }) socket.on("reg", function (user) { this.na1 = user; }) // 私發消息 socket.on('message1', function (data) { var p1 = document.createElement("div"); var s1 = document.createElement("p"); var s2 = document.createElement("p"); var div1 = document.createElement("div"); var em = document.createElement("em"); var ads = document.createElement("audio"); ads.src = "https://www.maomin.club/data/res.mp3"; ads.className = "ads"; s1.className = "chatlist"; s2.className = "chatlist1"; em.className = "zwasked1"; div1.className = "divbox"; s1.innerText = data.from; s2.innerText = data.msg; s1.appendChild(em); p1.appendChild(s1); p1.appendChild(s2); chat.appendChild(ads); ads.play(); div1.appendChild(p1); chat.appendChild(div1); chat.scrollTop = chat.scrollHeight; }); // 私聊發送 function send() { if (document.getElementById("text").value != "") { socket.emit('sayTo', { from: lo.value, to: document.querySelector(".tit").innerText, msg: document.querySelector("#text").value, }) var p1 = document.createElement("div"); var s1 = document.createElement("p"); var s2 = document.createElement("p"); var em = document.createElement("em"); var div1 = document.createElement("div"); var ads = document.createElement("audio"); p1.style.cssText = "float:right;"; s2.style.cssText = "color:#333;" ads.src = "https://www.maomin.club/data/s.wav"; ads.className = "ads"; div1.className = "divbox"; s1.className = "chatlist"; s1.style.cssText = "color:#333 !important;float:right; !important"; s2.className = "chatlist2"; em.className = "zwasked"; s1.innerText = lo.value; s2.innerText = document.querySelector("#text").value; s1.appendChild(em); p1.appendChild(s1); p1.appendChild(s2); chat.appendChild(ads); ads.play(); div1.appendChild(p1); chat.appendChild(div1); chat.scrollTop = chat.scrollHeight; } else { sweetAlert('請輸入內容!'); } chat.scrollTop = chat.scrollHeight; document.querySelector("#text").value = ""; document.querySelector("#text").focus(); }
后臺主要核心邏輯:
我這里只列舉了http環境的,完整代碼中有https環境的。
var http=require("http"); var fs=require("fs"); var express = require('express'); var ws=require("socket.io"); var path=require("path"); var _ = require('underscore'); var usocket = []; var usocket1 = []; var pass=[]; var data=[]; var hashName = {}; var onlineCount = 0; var app = express(); // 靜態文件識別 app.use(express.static(path.join(__dirname, './public'))); var server=http.createServer(function (req,res) { var filename = req.url.split('/')[req.url.split('/').length-1]; var suffix = req.url.split('.')[req.url.split('.').length-1]; if(req.url==='/'){ res.writeHead(200, {'Content-Type': 'text/html'}); var html = fs.readFileSync("./public/index.html"); res.end(html) }else if(suffix==='css'){ res.writeHead(200, {'Content-Type': 'text/css'}); res.end(get_file_content(path.join(__dirname, 'public', 'css', filename))); }else if(suffix==='js') { res.writeHead(200, {'Content-Type': 'text/javascript'}); res.end(get_file_content(path.join(__dirname, 'public', 'js', filename))); }else if (suffix in ['gif', 'jpeg', 'jpg', 'png']) { res.writeHead(200, { 'Content-Type': 'image/' + suffix }); res.end(get_file_content(path.join(__dirname, 'public', 'images', filename))); } }); function get_file_content(filepath) { return fs.readFileSync(filepath); } // 獲取在線 function broadcast() { io.sockets.emit("dataval", hashName); } //提供私有socket function privateSocket(toId) { return (_.findWhere(io.sockets.sockets, { id: toId })); } // 封裝刪除 function removeByValue(arr, val) { for (var i = 0; i < arr.length; i++) { if (arr[i] == val) { arr.splice(i, 1); break; } } } // 連接socket var io=ws(server); io.on("connection",function(socket){ // 寫入成功后讀取測試 fs.readFile('./user.xls', 'utf-8', function (err, data) { if(data!=null){ var value = data.split('\n'); io.sockets.emit("users", value); } }); // 寫入成功后讀取測試 fs.readFile('./password.xls', 'utf-8', function (err,data) { if(data!=null){ var pass1=data.split('\n'); io.sockets.emit("pass", pass1); } }); broadcast(); // 生成名字 socket.on('setName', function (data) { var name = data; hashName[name] = socket.id; // console.log(hashName[name]); broadcast(); }); // 私聊發送 socket.on('sayTo', function (data) { var toName = data.to; var toId; console.log(toName); if (toId = hashName[toName]) { privateSocket(toId).emit('message1', data); } }); // 離開 socket.on('disconnect', function (name) { name=this.i2; io.emit("disconnect", name); removeByValue(data, name); io.sockets.emit("dataval", data); }) // 在線 socket.on('time', function (val) { // console.log(val); }) // 注冊 socket.on("reg", function (name) { usocket[name] = socket; this.i1=name; io.emit("reg", name); var myname =this.i1+"\n"; fs.writeFile('./user.xls', myname, { 'flag': 'a' }, function (err) { if (err) { throw err; } // 寫入成功后讀取測試 fs.readFile('./user.xls', 'utf-8', function (err,data) { if (err) { throw err; } }); }); }) // 加入 io.emit('connected', ++onlineCount); // console.log(data); io.sockets.emit("array", data); socket.on("join", function (name) { usocket1[name] = socket; this.i2 = name; io.emit("join", name); data.push(name); io.sockets.emit("dataval", data); }) // 密碼 socket.on("pass",function(val){ pass[val]=socket; this.i2=val; io.emit("pass", val); var password=this.i2+"\n"; fs.writeFile('./password.xls', password, { 'flag': 'a' }, function (err) { if (err) { throw err; } }); }) }); server.listen(3003); console.log("服務器運行中");
這個項目是之前寫的,歡迎大家進行指正。大家可以復制下面的源碼地址,拉取下來就可以在本地實現一個聊天服務。如果你有服務器可以把它部署在服務器上,這樣你就可以有一個屬于自己的聊天App了。大家可以根據源碼進行學習,有不明白的可以隨時問我。
https://github.com/maomincoding/chat3
關于如何使用JavaScript與Node.js打造一款聊天App就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。