JavaScript与Node.js一起打造一款聊天App

Jacquelyn38 等级 887 0 1

聊天是我们人与人交流最直接的方式,互联网的加入使我们交流更加便捷。我们手机上的微信、QQ是我们手机必不可少的应用软件。那么,我们是否可以做一款聊天应用呢?

之前我自己闲着没事,研究过一些技术,做了一款即时通讯应用,下面我将选取几幅具有代表性的图片供大家参考。

一、应用示图

JavaScript与Node.js一起打造一款聊天App

JavaScript与Node.js一起打造一款聊天App

JavaScript与Node.js一起打造一款聊天App

JavaScript与Node.js一起打造一款聊天App

以上是这款应用的主要页面,功能可能相对简陋点,不过基本的功能已经实现了,下面我将给出核心代码,全部源码地址在文末。

二、部分核心源码

前台主要核心逻辑:

这里我只列举了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
  • 欢迎关注我的公众号前端历劫之路

  • 回复关键词电子书,即可获取12本前端热门电子书。

  • 回复关键词红宝书第4版,即可获取最新《JavaScript高级程序设计》(第四版)电子书。

  • 关注公众号后,点击下方菜单即可加我微信,我拉拢了很多IT大佬,创建了一个技术交流、文章分享群,期待你的加入。

  • 作者:Vam的金豆之路

  • 微信公众号:前端历劫之路

JavaScript与Node.js一起打造一款聊天App

JavaScript与Node.js一起打造一款聊天App

本文转自 https://mp.weixin.qq.com/s/mvpHMZqHYKA6jr1QfixQxA,如有侵权,请联系删除。

收藏
评论区

相关推荐

JavaScript基础加ES6语法
JavaScript 一、什么是JavaScript 当下最流行的脚本语言,在世界上的所有浏览器中都有js的身影,是一门脚本语言,可以用于我们与web站点和web应用程序的交互,还可以用于后台服务器的编写,例如node.js 二、语法特点 基于对象和事件驱动的松散型,解释型语言 单线程异步 三、JavaScript作用 页面的交
Node.js 如何处理 ES6 模块
Node.js 如何处理 ES6 模块作者: 日期: 学习 JavaScript 语言,你会发现它有两种格式的模块。一种是 ES6 模块,简称 ESM;另一种是 Node.js 专用的 CommonJS 模块,简称 CJS。这两种模块不兼容。很多人使用 Node.js,只会用require()加载模块,遇到 ES6
JavaScript与Node.js一起打造一款聊天App
聊天是我们人与人交流最直接的方式,互联网的加入使我们交流更加便捷。我们手机上的微信、QQ是我们手机必不可少的应用软件。那么,我们是否可以做一款聊天应用呢? 之前我自己闲着没事,研究过一些技术,做了一款即时通讯应用,下面我将选取几幅具有代表性的图片供大家参考。一、应用示图 以上是这款应用的主要页面,功能可能相对简陋点,不过基本的功能已经实现了,下面我将给出
vs2015中electron开发入门 01
### 安装vs2015插件\[node.js Tools\] 1.在vs工具->扩展更新,查找node关键字,找到如图 ![node.js Tools](https://static.oschina.net/uploads/img/201605/23225301_AcB3.png "node.js Tools") 2.下载安装插件 ### 创建项目
Electron 快速入门及最新安装教程
> 作者:程序员学院   官方网址:[https://www.chengxuyuan.com](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.chengxuyuan.com)    微信公众号:华仁程序员学院 一、 Electron简介 ------------- Electr
Native地图与Web融合技术的应用与实践
![](https://oscimg.oschina.net/oscnet/up-aad2c4fa385750c08df2ae9ab139e03c96b.JPEG) 1\. 背景 ------ 美团打车业务很早就在美团App与点评App中提供了服务入口,并在技术上采用了H5与Native的混合开发技术。随着业务上线,有用户反馈我们的地图性能有一些问题,原
Node.JS是什么?
百度上是这么说的:Node.js是一个可以快速构建网络服务及应用的平台。该平台的构建是基于Chrome‘s JavaScript runtime,也就是说,实际上它是对Goole V8引擎进行了封装。 **Node.js的优点** nodejs作为一个新兴的后台语言,有很多吸引人的地方: RESTful API 单线程 Node.js可以在不新增
Node.js
1.Node来历 --------     2009年,正是推出基于Javascript语言和V8引擎的开源Web服务项目,命名为Node.js,Node.js是第一次把Javascript带到后端开发。全很很多开发人员都熟悉Javascript,所以Node.js一下子就火了。     Javascript语言本身是完善的函数式语言,在前端开发时,开发
Node.js 安装与开发
**Node.js 简介** Node.js是一个Javascript运行环境(runtime),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js对一些特殊用例进行优化,提供替代的API,使得V8在非浏览器环境下运行得更好。 V8引擎执行Javascript的速度非常快,性能非常好。 Node.j
Node.js 简单学习
明白 JavaScript 语言,你就会用 Node.js 了。最常见的运行 JavaScript 语言的地方就是用户的浏览器,几乎所有的浏览器上都有个 JavaScript 引擎,这个引擎负责运行在页面中嵌入的 JavaScript 代码。代码是在用户的浏览器上运行的,用户那头叫前端(Frontend),服务器这头叫后端(Backend)。Node.js
Node.js学习路线图
Node.js学习路线图 ------------ [从零开始nodejs系列文章](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fblog.fens.me%2Fseries-nodejs%2F),将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs
Node.js简介及如何学习Node.js
本文介绍Node.js的诞生史以及如何学习Node.js。 Node.js简史 --------- 从Node.js的命名上可以看到,Node.js的官方开发语言是JavaScript。之所以选择使用JavaScript,显然与JavaScript的开发人员多有关。总所周知,JavaScript是伴随着互联网的发展而火爆起来的,JavaScript也是前
NodeJs在windows上安装配置测试
Node.js简介 简单的说 Node.js 就是运行在服务端的 JavaScript。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。Node.js 的包管理器 npm,是全球最大的开源库生态系统。 安装环境 本机系统:Windo
Node学习笔记
Node.js 教程目录 ============ 1. [Node.js 基础](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2Fwscats%2Fnode-tutorial%2Ftree%2Fmaster%2Ftutorial%2Fbase)
React Native与ExMobi技术路线探索
随着Facebook陆续开源React Native的iOS和Android版本,这种以JavaScript来开发原生APP的方式在移动应用开发圈里得到广泛关注,虽然React Native并不是第一个采用JavaScript编写原生APP的产品,但是其独特的设计思想和实现方式是非常值得借鉴的。 而作为国内老字号的移动应用开发平台,同样支持开发原生APP