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日

相关文章

  • Python flask框架端口失效解决方案

    下面是详细的“Python flask框架端口失效解决方案”的攻略。 问题描述 在使用Python Flask框架进行开发时,由于端口占用等原因,导致无法访问Web应用程序。 解决方案 方案一:手动指定端口 在Flask中,可以使用app.run()方法来运行Web应用程序。默认情况下,该方法运行在本地的5000端口上。如果该端口已经被占用,可以手动指定端口…

    Flask 2023年5月16日
    00
  • python案例中Flask全局配置示例详解

    我会详细讲解“python案例中Flask全局配置示例详解”的完整攻略,包含两条示例说明。 示例1:应用程序配置 在Flask中,应用程序配置代表应用程序级别的配置。这些配置可以通过修改应用程序实例的app.config字典来完成,如下所示: from flask import Flask app = Flask(__name__) app.config[‘…

    Flask 2023年5月15日
    00
  • CentOS7部署Flask(Apache、mod_wsgi、Python36、venv)

    下面是详细讲解 “CentOS7部署Flask(Apache、mod_wsgi、Python36、venv)” 的完整攻略。 环境准备 CentOS7 服务器系统; 安装 Apache Web 服务器; 安装 Python3.6 版本; 安装 mod_wsgi Apache 模块; 在系统上创建一个 Python3 的虚拟环境; Flask 应用程序开发 在…

    Flask 2023年5月15日
    00
  • Flask wtforms实现表单验证使用

    下面是详细的“Flask wtforms实现表单验证使用”的攻略: 一、前置知识 在使用 Flask wtforms 实现表单验证前,需要了解以下知识: Flask:Python Web 应用框架,提供了一个模块化的方式组织 Web 应用程序。 Flask wtforms:基于 Flask 的表单验证扩展,可以方便地进行表单验证。 HTML 表单:Web 表…

    Flask 2023年5月16日
    00
  • Flask项目的部署的实现步骤

    一、Flask项目的部署实现步骤 Flask是一个轻量级的Python Web框架,部署一个Flask应用涉及到的步骤通常包括以下几个方面: 1. 配置服务器环境因为Flask要运行在服务器上,所以必须要先确保服务器环境符合Flask运行的要求,包括搭建有效的Python环境、配置Web服务器等。 2. 安装Flask在服务器上安装Flask库,可以利用pi…

    Flask 2023年5月15日
    00
  • vue+flask实现视频合成功能(拖拽上传)

    下面是详细讲解“vue+flask实现视频合成功能(拖拽上传)”的完整攻略。 总体思路 这个项目的目的是实现用户可以通过拖拽上传多个视频文件,并将这些视频文件拼接成一个新的视频文件自定义保存,同时该视频文件可以在前端进行预览播放。 具体的实现方案是:前端使用vue框架构建视图,并使用dropzone.js插件实现文件的拖拽上传;后端使用flask框架运行py…

    Flask 2023年5月16日
    00
  • 关于Flask 视图介绍

    关于Flask视图的介绍主要包含以下内容。 什么是Flask视图 Flask视图是一种函数,用于处理来自客户端的请求并返回响应。在Flask中,视图函数被装饰器@app.route()所修饰。当客户端请求与修饰器中指定的URL相匹配时,Flask就会调用对应的视图函数来处理该请求。 from flask import Flask app = Flask(__…

    Flask 2023年5月16日
    00
  • 用 Flask 实现发送电子邮件

    Flask 是一款轻量级的 Web 框架,非常适合快速开发小型 Web 应用。 在这篇文章中,我们将详细介绍如何在 Flask 应用中发送邮件。 安装 Flask-Mail 扩展 首先,我们需要安装 Flask-Mail 扩展来发送邮件。可以使用下面的命令来安装 Flask-Mail: pip install Flask-Mail 接下来,我们需要设置 Fl…

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