vue使用WebSocket模拟实现聊天功能

下面是详细讲解“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的onopenonerroroncloseonmessage等事件。例如,在组件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技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • Flask框架的学习指南之用户登录管理

    标题:Flask框架的学习指南之用户登录管理 1.概述 Flask是一个非常流行的Python Web框架,灵活可扩展。在Web应用程序中,用户登录管理是必不可少的一项功能。Flask框架提供了快速构建用户认证和授权的工具。 2.安装Flask 在开始使用Flask之前,需要先安装Flask。可以使用pip来安装Flask: pip install Flas…

    Flask 2023年5月15日
    00
  • 在Python的Flask框架下使用sqlalchemy库的简单教程

    如果你准备使用Python Flask框架来开发web应用程序,那么SQLAlchemy库可以帮助你轻松与数据库进行交互。下面是一个基于Python Flask框架和SQLAlchemy库的简单教程: 安装依赖 在开始之前,请确保已经安装了Python和pip工具。然后,你需要使用pip安装Flask和SQLAlchemy库,你可以在命令行中输入以下命令: …

    Flask 2023年5月15日
    00
  • 详解Python的Flask框架中生成SECRET_KEY密钥的方法

    Flask 是一个使用 Python 编写的轻量级 Web 开发框架。在使用 Flask 开发 Web 应用时,通常需要生成 SECRET_KEY 密钥用于加密 Cookies、Session 等数据。以下是详解 Flask 生成 SECRET_KEY 密钥的方法。 方法一:使用 Flask 自带的生成密钥方法 在 Flask 中,可以使用 os.urand…

    Flask 2023年5月16日
    00
  • 一个基于flask的web应用诞生 组织结构调整(7)

    我来给你详细讲解一下。 “一个基于flask的web应用诞生 组织结构调整(7)”是一篇关于使用Flask框架搭建web应用的教程。其中,作者介绍了如何使用Flask框架来构建一个基础的web应用,并通过对项目的组织结构进行调整,使得代码更加清晰易懂,可维护性更高。 这篇教程主要包括以下内容: 创建Flask应用 通过使用Flask框架提供的API,可以快速…

    Flask 2023年5月15日
    00
  • Python利用Flask-Mail实现发送邮件详解

    下面是Python利用Flask-Mail实现发送邮件的完整攻略: 一、Flask-Mail简介 Flask-Mail是Flask框架的一个扩展模块,可以使发送电子邮件更方便。它提供了SMTP认证、HTML邮件等功能,使用起来十分简单。 二、安装Flask-Mail 在使用Flask-Mail之前,需要先安装Flask-Mail扩展。使用pip安装即可: p…

    Flask 2023年5月16日
    00
  • js实现录音上传功能

    下面我会为你详细讲解如何使用JS实现录音上传功能。 背景介绍 录音上传功能是一种常见的Web应用程序功能,它可以使用户在Web端录制音频并将其上传到服务器上。这种功能可以用于许多应用,比如在线音乐教育、在线语音识别、在线语音聊天等等。 实现录音上传功能需要使用Web开发中的一种技术,Web Audio API。Web Audio API提供了一个丰富、强大的…

    Flask 2023年5月16日
    00
  • 如何使用Flask-Migrate拓展数据库表结构

    使用Flask-Migrate拓展数据库表结构的步骤如下: 安装Flask-Migrate 在终端或命令行输入以下命令:pip install Flask-Migrate 配置Flask-Migrate 在Flask应用程序中,导入Flask-Migrate扩展并初始化它。使用以下代码创建一个migrate对象: “`python from flask_m…

    Flask 2023年5月16日
    00
  • flask框架json数据的拿取和返回操作示例

    下面我将为你详细讲解“flask框架json数据的拿取和返回操作示例”的完整攻略,包含两条示例说明。 一、获取JSON数据 在Flask框架中获取JSON数据很容易,我们只需要通过request对象的get_json()方法即可获取提交的JSON数据。下面是一个简单的示例: from flask import Flask, request, jsonify …

    Flask 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部