共分为两个界面,一个websocket服务器js页,一个vue.config.js页,一个路由页,用了vant UI 版本2.12.54,vue版本2.6.14 记得npm install ws模块 版本8.13.0,使用的node版本16.14.0。
gitee地址liaotian: websocket和vue实现的简易局域网多人聊天
1.home页也是登录页
<template>
<div class="home">
<div class="lit">全民聊天室</div>
<van-form @submit="onSubmit">
<van-field
v-model="username"
name="用户名"
label="用户名"
placeholder="用户名"
:rules="[{ required: true, message: '请填写用户名' }]"
/>
<van-field
v-model="password"
type="password"
name="密码"
label="密码"
placeholder="密码"
:rules="[{ required: true, message: '请填写密码' }]"
/>
<div style="margin: 16px">
<van-button round block type="info" native-type="submit"
>进入聊天室</van-button
>
</div>
</van-form>
</div>
</template>
<script>
export default {
data() {
return {
username: '',
password: '',
};
},
methods: {
onSubmit() {
this.$router.push({
name:'about',
params:{
name:this.username
}
})
},
},
}
</script>
<style scoped>
.lit{
margin:40px 0;
font-size: 20px;
text-align: center;
}
</style>
2.about页也是聊天页
<template>
<div class="about">
<div class="lit">全民聊天室</div>
<div class="about-box" ref="about">
<div
class="liao"
:class="{ liao1: item.name === $route.params.name }"
v-for="(item, index) in list"
:key="index"
>
<div class="tou" :class="{ tou1: item.name === $route.params.name }">
{{ item.userId }}
</div>
<div class="info" :class="{ info1: item.name === $route.params.name }">
<div
class="info-name"
:class="{ infoname1: item.name === $route.params.name }"
>
{{ item.name }}
</div>
<div
class="info-content"
:class="{ infocontent1: item.name === $route.params.name }"
>
{{ item.content }}
</div>
</div>
</div>
<!-- <div :class="{liao1: item.name=$route.params.name}">
<div class="info1">
<div class="info-name1"></div>
<div class="info-content1"></div>
</div>
<div class="tou1"></div>
</div> -->
</div>
<van-field class="ipt" v-model="contentText" center clearable ref="sendMsg">
<template #button>
<van-button size="small" type="primary" @click="btn">发送</van-button>
</template>
</van-field>
</div>
</template>
<script>
import { Dialog } from 'vant';
export default {
data () {
return {
userInfo: {
type: "name",
data: '',
head: ''
},
ws: null,
count: 0,
userId: null, //当前用户ID
list: [], //聊天记录的数组
contentText: "" //input输入的值
}
},
created () {
},
mounted () {
this.initWebSocket();
},
updated () {
this.scrollBottm()
},
methods: {
btn () {
if (!this.$route.params.name) {
Dialog({
title: '警告',
message: '登录信息已失效,请重新登录',
}).then(() => {
this.$router.back()
});
return
}
let me = {
tou: this.$route.params.name.charAt(0),
name: this.$route.params.name,
content: this.contentText
}
if (!this.contentText) {
return;
}
this.sendText(me)
// let bie=`<div class="liao" >
// <div class="tou">{{item.tou}}</div>
// <div class="info">
// <div class="info-name">{{item.name}}</div>
// <div class="info-content">{{item.content}}</div>
// </div>
// </div>`
// let m=`<div class="liao1">
// <div class="info1">
// <div class="info-name1">${me.name}</div>
// <div class="info-content1">${me.content}</div>
// </div>
// <div class="tou1">${me.tou}</div>
// </div>`
// this.$refs.about.innerHTML+=m
// this.list.push(me)
// this.$refs.about.innerHTML+=bie
this.initWebSocket();
},
scrollBottm () {
let el = this.$refs["about"];
el.scrollTop = el.scrollHeight;
console.log(el.scrollHeight);
},
//发送聊天信息
sendText (me) {
let _this = this;
_this.$refs["sendMsg"].focus();
if (!_this.contentText) {
return;
}
_this.ws.send(JSON.stringify(me)); //调用WebSocket send()发送信息的方法
_this.contentText = "";
setTimeout(() => {
_this.scrollBottm();
}, 500);
},
//进入页面创建websocket连接
initWebSocket () {
let _this = this;
//判断页面有没有存在websocket连接
if (window.WebSocket) {
// 10.12.16.27:8181 是我本地IP地址 此处的 :8181 端口号 要与后端配置的一致
let ws = new WebSocket("ws:192.168.1.97:8181");
_this.ws = ws;
ws.onopen = function (e) {
console.log("服务器连接成功" + e);
};
ws.onclose = function (e) {
console.log("服务器连接关闭" + e);
};
ws.onerror = function () {
console.log("服务器连接出错");
};
ws.onmessage = function (e) {
//接收服务器返回的数据
let resData = JSON.parse(e.data);
console.log(resData);
if (resData.funName == "userCount") {
_this.count = resData.users;
_this.list = resData.chat
console.log(resData.chat);
} else {
_this.list = [
..._this.list,
];
}
};
}
}
},
}
</script>
<style>
.lit {
text-align: center;
}
.about-box {
height: 155vw;
background-color: gainsboro;
padding-bottom: 53px;
display: flex;
flex-direction: column;
overflow-y: auto;
}
.liao {
padding: 10px;
display: flex;
/* width: 100%; */
padding-right: 20px;
margin-bottom: 10px;
}
.tou {
width: 30px;
height: 30px;
border-radius: 50%;
background-color: white;
text-align: center;
line-height: 30px;
margin-right: 10px;
}
.info-content {
box-sizing: content-box;
background-color: white;
padding: 5px;
border-radius: 5px;
margin-top: 5px;
max-width: 81vw;
}
.liao1 {
/* width: 100%; */
padding: 1px;
display: flex;
justify-content: flex-end;
padding-left: 20px;
margin-bottom: 10px;
}
.tou1 {
width: 30px;
height: 30px;
border-radius: 50%;
background-color: white;
text-align: center;
line-height: 30px;
margin-right: 10px;
margin-left: 10px;
order: 1;
}
.info1 {
/* flex: 1; */
order: 0;
}
.infoname1 {
text-align: right;
}
.infocontent1 {
box-sizing: border-box;
background-color: rgb(25, 184, 7);
padding: 5px;
border-radius: 5px;
margin-top: 5px;
max-width: 81vw;
}
.ipt {
position: fixed;
bottom: 0;
left: 0;
}
</style>
3.serves.js页也是服务器页
var userNum = 0; //统计在线人数
var chatList = [];//记录聊天记录
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ host:'192.168.1.97',port: 8181 }); //8181 与前端相对应
//调用 broadcast 广播,实现数据互通和实时更新
wss.broadcast = function (msg) {
wss.clients.forEach(function each (client) {
client.send(msg);
});
};
wss.on('connection', function (ws) {
userNum++;//建立连接成功在线人数 +1
wss.broadcast(JSON.stringify({ funName: 'userCount', users: userNum, chat: chatList })); //建立连接成功广播一次当前在线人数
console.log('Connected clients:', userNum);
//接收前端发送过来的数据
ws.on('message', function (e) {
var resData = JSON.parse(e)
console.log('接收到来自clent的消息:' + resData.name)
chatList.push({ userId: resData.tou, name: resData.name, content: resData.content });//每次发送信息,都会把信息存起来,然后通过广播传递出去,这样此每次进来的用户就能看到之前的数据
wss.broadcast(JSON.stringify({ userId: resData.tou, name: resData.name, msg: resData.content })); //每次发送都相当于广播一次消息
});
ws.on('close', function () {
userNum--;//建立连接关闭在线人数 -1
wss.broadcast(JSON.stringify({ funName: 'userCount', users: userNum, chat: chatList }));//建立连接关闭广播一次当前在线人数
console.log('Connected clients:', userNum);
console.log('长连接已关闭')
})
})
console.log(wss)
4.vue.config.js页
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
// https:true,
// lintOnSave: false,
// port: 8181,
client: {
webSocketURL: 'ws://192.168.1.97:8181', //电脑ip地址
},
// headers: {
// 'Access-Control-Allow-Origin': '*',
// },
// disableHostCheck: true,
historyApiFallback: true, //跨不跨的没有啥影响
allowedHosts: 'all',
proxy: {
'ws': {
target: `ws://localhost:8181`, //自定义的请求后台接口
ws: true,
changeOrigin: true, //允许跨域
}
},
},
})
5.路由配置
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue')
}
]
const router = new VueRouter({
routes
})
export default router
6.目录
先启动服务器再运行项目!