下面是详细讲解“vue使用WebSocket模拟实现聊天功能”的攻略。
一、背景介绍
WebSocket协议是HTML5出现后新增的一项协议,基于TCP协议,可以实现客户端和服务器的双向通信。相比传统的Ajax轮询或Comet长轮询方式,WebSocket具有更低的延迟、更高的性能和更强的兼容性。
在Vue中使用WebSocket可以实现实时更新数据、聊天功能等。下面讲解如何使用WebSocket模拟实现前端聊天功能。
二、使用WebSocket模拟实现简单聊天功能
1.创建WebSocket
在Vue组件中,使用WebSockets来建立与服务器之间的连接。可以在组件的created或mounted钩子函数中创建WebSocket实例:
mounted() {
const ws = new WebSocket('ws://localhost:3000');
ws.onmessage = this.handleMessage;
this.ws = ws;
},
2.发送消息
WebSocket中发送消息是使用send()
方法,我们可以在组件方法中发送消息:
handleSend() {
const message = this.message;
this.ws.send(message);
}
3.接收消息
WebSocket的接收消息是使用onmessage
事件,在组件中定义事件处理函数:
handleMessage(event) {
const data = event.data;
console.log(data);
this.messageList.push(data);
}
4.显示聊天记录
将聊天记录渲染到页面上,可以使用v-for指令遍历消息列表:
<div v-for="message in messageList" :key="message">{{ message }}</div>
5.完整代码
下面是一个简单的聊天组件的完整代码示例:
<template>
<div>
<div v-for="message in messageList" :key="message">{{ message }}</div>
<input type="text" v-model="message" />
<button @click="handleSend">发送</button>
</div>
</template>
<script>
export default {
name: "Chat",
data() {
return {
message: "",
messageList: [],
ws: null
};
},
mounted() {
const ws = new WebSocket("ws://localhost:3000");
ws.onmessage = this.handleMessage;
this.ws = ws;
},
methods: {
handleSend() {
const message = this.message;
this.ws.send(message);
},
handleMessage(event) {
const data = event.data;
console.log(data);
this.messageList.push(data);
}
}
};
</script>
三、使用WebSocket模拟实现高级聊天功能
除了简单的实时聊天,我们可以使用WebSocket模拟实现更复杂的功能,例如“在线用户列表”、“发送图片”等。
1.监听WebSocket连接
在服务器端,需要监听WebSocket连接,当有新的WebSocket连接时,保存该连接的WebScoket实例,便于后续操作。
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 3000 });
const users = new Map();
wss.on("connection", function connection(ws) {
ws.on("message", function incoming(message) {
handleMessage(ws, message);
});
ws.on("close", function() {
handleDisconnect(ws);
});
ws.on("error", function(e) {
console.log(e);
});
});
function handleMessage(ws, message) {
const data = JSON.parse(message);
const action = data.action;
switch (action) {
case "LOGIN":
handleLogin(ws, data);
break;
case "LOGOUT":
handleLogout(ws);
break;
case "MESSAGE":
handleMessageSend(ws, data);
break;
case "IMAGE":
handleImageSend(ws, data);
break;
default:
break;
}
}
function handleLogin(ws, data) {
const { userId } = data;
users.set(userId, ws);
broadcast(ws, {
type: "USER_LIST",
data: Array.from(users.keys())
});
}
function handleLogout(ws) {
const user = [...users].find(([key, value]) => value === ws);
if (user) {
users.delete(user[0]);
broadcast(ws, {
type: "USER_LIST",
data: Array.from(users.keys())
});
}
console.log("disconnect");
}
function handleMessageSend(ws, data) {
const { userId, message } = data;
const targetWs = users.get(userId);
if (targetWs) {
targetWs.send(
JSON.stringify({
type: "MESSAGE",
data: {
userId: userId,
message: message
}
})
);
}
}
function handleImageSend(ws, data) {
const { userId, imageUrl } = data;
const targetWs = users.get(userId);
if (targetWs) {
targetWs.send(
JSON.stringify({
type: "IMAGE",
data: {
userId: userId,
imageUrl: imageUrl
}
})
);
}
}
function handleDisconnect(ws) {
const user = [...users].find(([key, value]) => value === ws);
if (user) {
users.delete(user[0]);
broadcast(ws, {
type: "USER_LIST",
data: Array.from(users.keys())
});
}
}
function broadcast(ws, data) {
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(data));
}
});
}
2.服务端处理消息
在服务端,使用WebSocket实现的聊天功能,需要根据业务需求包装不同的消息格式。例如,发送消息时包装成:
{
type: 'MESSAGE',
data: {
userId: 'xxx',
message: 'test message'
}
}
发送图片时包装成:
{
type: 'IMAGE',
data: {
userId: 'xxx',
imageUrl: 'http://xxx.jpg'
}
}
3.监听WebSocket事件
在Vue中,可以监听WebSocket的onopen
、onerror
、onclose
和onmessage
等事件。例如,在组件mounted钩子中监听WebSocket的连接和消息:
mounted() {
const ws = new WebSocket("ws://localhost:3000");
ws.onopen = this.handleOpen;
ws.onerror = this.handleError;
ws.onclose = this.handleClose;
ws.onmessage = this.handleMessage;
this.ws = ws;
},
4.发送和接收消息
发送和接收消息的示例代码如下所示:
handleSend() {
const message = {
action: "MESSAGE",
userId: this.userId,
message: this.message
};
this.ws.send(JSON.stringify(message));
this.message = "";
},
handleImageSend(event) {
const file = event.target.files[0];
const formData = new FormData();
formData.append("image", file);
const message = {
action: "IMAGE",
userId: this.userId
};
this.uploadImage(formData, message);
},
handleMessage(event) {
const data = JSON.parse(event.data);
const type = data.type;
const messageType = {
MESSAGE: "message",
IMAGE: "image",
USER_LIST: "userList"
}[type];
const messageData = data.data;
const userId = messageData.userId;
const messageContent = messageData.message || messageData.imageUrl;
this.messageList.push({
type: messageType,
userId: userId,
content: messageContent
});
}
5.完整代码
下面是实现完整功能的Vue组件的代码示例:
<template>
<div>
<div class="user-list">
<div v-for="userId in userList" :key="userId">{{ userId }}</div>
</div>
<div class="chat-log">
<div class="message" v-for="message in messageList" :key="message.id">
<div v-if="message.type === 'message'">{{ message.userId }}:{{ message.content }}</div>
<div v-if="message.type === 'image'"><img :src="message.content" /></div>
</div>
</div>
<div class="chat-input">
<input type="text" v-model="message">
<button @click="handleSend">发送</button>
<input type="file" accept="image/*" @change="handleImageSend" />
</div>
</div>
</template>
<script>
export default {
name: "Chat",
data() {
return {
userId: "user1",
message: "",
messageList: [],
ws: null,
userList: []
};
},
mounted() {
const ws = new WebSocket("ws://localhost:3000");
ws.onopen = this.handleOpen;
ws.onerror = this.handleError;
ws.onclose = this.handleClose;
ws.onmessage = this.handleMessage;
this.ws = ws;
},
methods: {
handleClose() {
console.log("close");
},
handleError(event) {
console.log(event);
},
handleOpen() {
console.log("open");
const message = {
action: "LOGIN",
userId: this.userId
};
this.ws.send(JSON.stringify(message));
},
handleSend() {
const message = {
action: "MESSAGE",
userId: this.userId,
message: this.message
};
this.ws.send(JSON.stringify(message));
this.message = "";
},
handleImageSend(event) {
const file = event.target.files[0];
const formData = new FormData();
formData.append("image", file);
const message = {
action: "IMAGE",
userId: this.userId
};
this.uploadImage(formData, message);
},
handleMessage(event) {
const data = JSON.parse(event.data);
const type = data.type;
const messageType = {
MESSAGE: "message",
IMAGE: "image",
USER_LIST: "userList"
}[type];
const messageData = data.data;
const userId = messageData.userId;
const messageContent = messageData.message || messageData.imageUrl;
this.messageList.push({
type: messageType,
userId: userId,
content: messageContent
});
if (type === "USER_LIST") {
this.userList = messageData;
}
},
uploadImage(formData, message) {
axios
.post("http://localhost:3000/upload", formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(response => {
message.imageUrl = response.data.url;
this.ws.send(JSON.stringify(message));
})
.catch(function(error) {
console.log(error);
});
}
}
};
</script>
<style>
.user-list {
display: flex;
flex-direction: column;
width: 100px;
}
.chat-log {
height: 300px;
}
.chat-log .message {
display: flex;
}
.chat-log .message img {
max-width: 100px;
max-height: 100px;
}
.chat-input {
display: flex;
flex-direction: column;
}
</style>
以上就是使用WebSocket模拟实现聊天功能的完整攻略。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue使用WebSocket模拟实现聊天功能 - Python技术站