NodeJS聊天室

跟着教学视频了解到websocket和socket.io的通信方法之后,自己写了一个交互效果更好的聊天室。

▍演示效果

▍实现过程(Windows系统)

1、在nodeJS中文网下载nodeJS客户端并安装;

2、在桌面(未知可自选)创建一个项目文件夹用于存放相关文件;

3、打开新建的文件夹,创建chatRoom.html文件和server.js文件;

4、打开命令行窗口,找到这个文件夹后,输入【npm i socket.io】,此时将在该文件夹中生成了一个新的文件夹,这是刚刚下载的socket.io相关依赖包;

5、将代码补充到chatRoom.html文件和server.js文件中;

6、打开命令行窗口,找到该项目文件夹后,输入【server.js】并【Enter】。

7、保持窗口在运行状态,不要关闭!!!

▍有待完善的地方

1、没有实现动态的分配身份;

2、界面可再优化;

3、前台向后台发送中文姓名时会出现乱码(找了两天资料都没有搞定,跪求大佬指教)。

▍server.js

// 引入http标准模块,CommonJS模块
const http = require("http");
const fs = require("fs");
const ws = require("socket.io");

// 当前在线人数
let count = 0;

// 总访客人数
let totalCount = 0;

// 创建一个web服务器
const server = http.createServer(function(request, response) {
	response.writeHead(200, {
		"Content-Type": "text/html;charset=UTF-8"
	});

	// 读取文件
	const html = fs.readFileSync("chatRoom.html");
	response.end(html);

});

// 基于当前web服务器开启socket实例
const io = ws(server);

// 检测连接事件
io.on("connection", function(socket) {

	console.log("当前有用户连接");
	count++;
	totalCount++;
	console.log("count:" + count);

	let name = '';

	// 加入群聊
	socket.on("join", function(message) {
		console.log(message);
		name = message.name;
		console.log(name + "加入了群聊");
        
        // 给公众发消息
		socket.broadcast.emit("joinNoticeOther", {
			name: name,
			action: "加入了群聊",
			count: count
		});

        // 给自己发消息
		socket.emit("joinNoticeSelf", {
			count: count,
			id: totalCount
		});
	});

	// 接收客户端所发送的信息
	socket.on("message", function(message) {
		console.log(message);
		// 向所有客户端广播发布的消息
		io.emit("message", message);
	});

	//	 监听到连接断开
	socket.on("disconnect", function() {
		count--;
		console.log(name + "离开了群聊")
		io.emit("disconnection", {
			count: count,
			name: name
		});
	});

});

// 服务器监听端口
server.listen(3000);

▍chatRoom.html

<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<title>蜗牛先生的聊天室</title>
		<style>
			* {
				margin: 0;
				padding: 0;
			}
			
			html {
				width: 100%;
				height: 100%;
				display: flex;
				justify-content: center;
				align-items: center;
				overflow: hidden;
				background-color: #DDDDDD;
			}
			
			.chatroom {
				width: 1000px;
				height: 600px;
				display: flex;
				border-radius: 20px;
				overflow: hidden;
				opacity: 0.7;
				box-shadow: 0 0 3px 3px #BBBBBB;
			}
			
			.left {
				width: 30%;
				height: 100%;
				display: flex;
				flex-direction: column;
				justify-content: center;
				align-content: center;
				background-color: #F0F0F0;
			}
			
			.icon-container {
				height: 30%;
				display: flex;
				justify-content: center;
				align-items: center;
			}
			
			.icon-container img {
				width: 150px;
				height: 150px;
				object-fit: cover;
				border-radius: 50%;
			}
			
			.self-container {
				height: 30%;
				display: flex;
				flex-direction: column;
				justify-content: center;
				align-items: center;
				line-height: 60px;
			}
			
			.self-container .id {
				font-size: 30px;
				font-weight: bold;
			}
			
			.self-container .content {
				display: flex;
				flex-direction: row;
				justify-content: space-around;
				font-size: 22px;
			}
			
			.note-container {
				/*margin: 10px;*/
				padding: 5px;
				height: 30%;
				/*border-radius: 10px;*/
				/*background-color: white;*/
			}
			
			.right {
				/*border-left: 1px solid #888888;*/
				width: 70%;
				height: 100%;
				/*background-image: url(http://p4.so.qhmsg.com/bdr/_240_/t010d7efb6430fb56d9.jpg);*/
				background-color: #EEEEEE;
			}
			
			.right .head {
				height: 10%;
				width: 100%;
				display: flex;
				justify-content: center;
				align-items: center;
				background-color: white;
				font-size: 22px;
				font-weight: bold;
			}
			
			.right .chat-container {
				padding: 10px;
				height: 80%;
				overflow-y: scroll;
				background-color: #F5F5F5;
				background-image: url(http://tool.uixsj.cn/qchan/uploads/2018/08/traffic_a_lot_of_cars_driving_across_the_golden_gate_bridge_free_stock_photos_picjumbo_HNCK2899_2210x1474.jpg);
				box-sizing: border-box;
			}
			/*滚动条样式*/
			
			.right .chat-container::-webkit-scrollbar {
				/*滚动条整体样式*/
				width: 8px;
				/*高宽分别对应横竖滚动条的尺寸*/
				height: 8px;
			}
			
			.right .chat-container::-webkit-scrollbar-thumb {
				/*滚动条里面小方块*/
				border-radius: 2rem;
				/*-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);*/
				background-color: #AAAAAA;
			}
			
			.right .chat-container::-webkit-scrollbar-track {
				/*滚动条里面轨道*/
				/*-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);*/
				border-radius: 2rem;
				background-color: transparent;
			}
			
			.right .chat-container .message-self,
			.right .chat-container .message-other {
				padding: 10px;
				box-sizing: border-box;
			}
			
			.right .chat-container .message-self {
				width: 100%;
				display: flex;
				flex-direction: row;
				flex-wrap: nowrap;
				justify-content: flex-end;
			}
			
			.right .chat-container .message-other {
				width: 100%;
				display: flex;
				flex-direction: row;
				flex-wrap: nowrap;
				/*justify-content: flex-start;*/
			}
			
			.right .chat-container .message-container {
				max-width: 80%;
				/*height: auto;*/
				display: flex;
				flex-direction: row;
				/*box-sizing: border-box;*/
			}
			
			.right .chat-container .message-self .message-container .message-content {
				padding-right: 10px;
			}
			
			.right .chat-container .message-other .message-container .message-content {
				padding-left: 10px;
			}
			
			.right .chat-container .message-self .message-container .message-content .message {
				background-color: blue;
				color: white;
			}
			
			.right .chat-container .message-other .message-container .message-content .message {
				background-color: white;
				color: black;
			}
			
			.right .chat-container .message-container .message-content .name {
				font-size: 12px;
				padding: 5px 0;
				color: #888888;
			}
			
			.right .chat-container .message-self .message-container .message-content .name {
				text-align: right;
			}
			
			.right .chat-container .message-other .message-container .message-content .name {
				text-align: left;
			}
			
			.right .chat-container .message-container .message-content .message {
				border-radius: 10px;
				padding: 10px;
			}
			
			.right .chat-container .message-container .icon img {
				width: 40px;
				height: 40px;
				object-fit: cover;
				border-radius: 50%;
			}
			
			.right .chat-container .notify-container {
				width: 100%;
				height: 50px;
				display: flex;
				justify-content: center;
				align-items: center;
			}
			
			.right .chat-container .notify-container .notify {
				border-radius: 10px;
				padding: 5px 10px;
				background-color: #999999;
				opacity: 0.9;
				font-size: 12px;
				color: white;
			}
			
			.right .input-container {
				width: 100%;
				height: 10%;
				display: flex;
				flex-direction: row;
				justify-content: space-between;
				background-color: blue;
				font-size: 18px;
			}
			
			.right .input-container .input-content {
				position: relative;
				width: 85%;
				background-color: white;
			}
			
			.right .input-container .input-content input {
				border: 0;
				padding: 10px;
				width: 100%;
				height: 100%;
				box-sizing: border-box;
				/* 去除input框外边框  */
				outline: none;
				font-size: 18px;
			}
			
			.right .input-container .input-content .num {
				position: absolute;
				right: 0;
				top: 0;
				width: 70px;
				height: 100%;
				display: flex;
				justify-content: center;
				align-items: center;
				background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 1));
				font-weight: bold;
				color: #333333;
			}
			
			.right .input-container .input-content input::-webkit-input-placeholder {
				font-size: 18px;
			}
			
			.right .input-container .send {
				width: 15%;
				display: flex;
				justify-content: center;
				align-items: center;
				background-color: orange;
				font-weight: bold;
			}
		</style>
	</head>

	<body>

		<div class="chatroom">

			<!--左侧-->
			<div class="left">

				<!--头像-->
				<div class="icon-container">

					<img src="https://i.niupic.com/images/2018/08/10/5yxS.jpg" />

				</div>

				<!--个人简介-->
				<div class="self-container">

					<div class="id">号码</div>

					<div class="content">

						<!--姓名-->
						<div class="name">姓名</div>|

						<!--性别-->
						<div class="gender">男</div>|

						<!--年龄-->
						<div class="age">32岁</div>

					</div>

				</div>

				<!--聊天室说明-->
				<div class="note-container"></div>

			</div>

			<!--右侧-->
			<div class="right">

				<!--顶部固定导航-->
				<div class="head">聊天室(<span id="count">0</span>)</div>

				<!--聊天记录-->
				<div class="chat-container">

				</div>

				<!--底部输入框-->
				<div class="input-container">

					<div class="input-content">
						<input id="msg" autofocus="autofocus" value="" oninput="inputMessage()" placeholder="请输入聊天内容…" />
						<div class="num">0/30</div>
					</div>

					<div class="send" onclick="send()">发送</div>

				</div>

			</div>

		</div>

		<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
		<script src="http://wulv5.com/js/socket.io.min.js"></script>
		<script>
			// 建立连接
			const socket = io.connect("/");

			// 编号
			let id = 0;

			// 允许输入的最大字数
			const maxInput = 30;

			// 用户头像
			let icon = 'https://i.niupic.com/images/2018/08/10/5yxS.jpg';

			// 用户姓名
			let name = '';

			getName();

			// 如果监听到socket消息,那么执行该回调函数,并得到广播消息
			// 此处的message参数是后台广播的内容
			socket.on("message", function(message) {
				console.log(message)
				let html = '';
				//				const container = document.getElementsByClassName("chat-container");
				if(name == message.name) {
					html = '<div class="message-self"><div class="message-container"><div class="message-content"><div class="name">' + message.name + '</div><div class="message">' + message.msg + '</div></div><div class="icon"><img src="' + icon + '" /></div></div></div>';
				} else {
					html = '<div class="message-other"><div class="message-container"><div class="icon"><img src="' + icon + '" /></div><div class="message-content"><div class="name">' + message.name + '</div><div class="message">' + message.msg + '</div></div></div></div>';
				}
				$(".chat-container").append(html);
				scrollToBottom();
			});

			// 接收到系统通知
			socket.on("joinNoticeSelf", function(message) {
				$("#count").text(message.count);
				id = message.id;
				$(".id").text(message.id + '号');
			});

			// 接收到系统通知
			socket.on("joinNoticeOther", function(message) {
				console.log("joinNoticeOther:");
				console.log(message);
				$("#count").text(message.count);
				const msg = {
					name: message.name,
					action: message.action
				}
				notify(msg);
			});

			// 断开连接回调事件
			socket.on("disconnection", function(message) {
				console.log(message);
				$("#count").text(message.count);
				const notifyMessage = {
					name: message.name,
					action: "退出了群聊"
				};
				notify(notifyMessage);
			});

			document.onkeydown = function(event) {
				var e = event || window.event || arguments.callee.caller.arguments[0];
				if(e && e.keyCode == 13) { // enter 键
					send();
				}
			};

			/**
			 * 发送系统通知
			 * 
			 * @param {Object} message
			 */
			function notify(message) {
				const notify = '<div class="notify-container"><div class="notify"><span class="name">' + message.name + '</span>' + message.action + '</div></div>';
				$(".chat-container").append(notify);
				scrollToBottom();
			}

			/**
			 * 固定滚动条到底部
			 */
			function scrollToBottom() {
				$(".chat-container").scrollTop($(".chat-container")[0].scrollHeight);
			}

			/**
			 * 获取姓名
			 */
			function getName() {
				const str = prompt("请输入你的名字", "");
				if(str) {
					name = str;
					console.log(name)
					$(".self-container .name").text(str);
					const message = {
						name: name
					}
					socket.emit("join", message);
				} else {
					getName();
				}
			}

			/**
			 * 输入消息
			 */
			function inputMessage() {
				const msg = $("#msg").val();
				const length = $("#msg").val().length;
				if(length > maxInput) {
					$("#msg").val(msg.substr(0, maxInput));
					$(".num").text(maxInput + '/' + maxInput);
				} else {
					const text = length + '/' + maxInput;
					$(".num").text(text);
				}
			}

			/**
			 * 发送消息
			 */
			function send() {
				var msg = $("#msg").val();

				if("" == name) {
					getName();
				} else {
					if("" == msg) {

					} else {
						const message = {
							id: id,
							name: name,
							msg: msg
						};
						// 通过socket发送消息
						socket.send(message);
						scrollToBottom();
						$("#msg").val("");
						$(".num").text('0/' + maxInput);
					}
				}
			}
		</script>

	</body>

</html>

猜你喜欢

转载自blog.csdn.net/i_dont_know_a/article/details/81585135