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

yizhihongxing

下面是详细讲解“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. 简单介绍异步和非阻塞概念 在这个部分,我们会对异步编程与非阻塞编程进行概念的简单介绍,包括它们的异同点以及其在网络编程中的运用。 2. Flask框架基础 本文中我们使用 Flask 框架实现异步编程和非阻塞编程的功能。在这一部分,我们将会介绍 Flask 的相关概念、基本使用方式…

    Flask 2023年5月15日
    00
  • Python入门学习之Python流处理过程

    Python入门学习之Python流处理过程 什么是流 流,是一种用来表示连续信息的概念。它通常是指一种数据读/写方式,逐个读取或逐个写入数据,每个数据单元被称为流上的记录或元素。流是一种以序列方式对数据进/出进行处理的方式,表现为数据流向的可见和不可见性,很多运算可以结合流的特点来实现,如MapReduce、Spark等大数据处理框架都可以看作是流处理的典…

    Flask 2023年5月16日
    00
  • 在Python的Flask框架中使用日期和时间的教程

    在Python的Flask框架中使用日期和时间,主要可以通过以下步骤来完成: 一、引用flask框架和datetime库 在Python的Flask框架中使用日期和时间时,需要先引用Flask框架和Python自带的datetime库: from flask import Flask, jsonify import datetime 其中,Flask是Pyt…

    Flask 2023年5月15日
    00
  • flask解析海康摄像头视频的使用

    首先,需要明确一下什么是Flask。Flask是一个基于Python的轻量级Web框架,开发者可以使用Flask快速构建Web应用程序。这里将介绍如何使用Flask解析海康摄像头视频。 步骤一:安装Flask和相关依赖 在开始之前,需要先安装Flask以及相关依赖。可以使用pip安装,执行以下命令: pip install flask flask-cors …

    Flask 2023年5月16日
    00
  • Django中信号signals的简单使用方法

    下面是Django中信号signals的简单使用方法: 什么是信号signals? 信号signals是Django提供的一种机制,通过该机制,某些操作的完成可以触发指定的处理函数,我们可以在这些处理函数中实现一些自己想要的操作。比如:在用户注册成功后,我们想给他发送一封欢迎电子邮件,那么我们就可以使用信号来实现这个功能。 Django中的信号signals…

    Flask 2023年5月16日
    00
  • mvc框架打造笔记之wsgi协议的优缺点以及接口实现

    我来为你详细讲解“MVC框架打造笔记之WSGI协议的优缺点以及接口实现”的完整攻略。 WSGI协议的优缺点 优点 WSGI协议的优点主要有以下几点: WSGI协议是Python Web框架的标准化统一接口,可以让不同的Web框架之间互相兼容和共享资源。 WSGI协议提供了一种简单、轻量级的Web应用程序接口,可以让开发者轻松地构建Web应用程序,同时可以选择…

    Flask 2023年5月16日
    00
  • Python Tornado之跨域请求与Options请求方式

    下面是针对“Python Tornado之跨域请求与Options请求方式”的完整攻略,包含两条示例说明: 背景 在开发Web应用中,经常会遇到前后端分离的开发模式。面对前后端分离开发,跨域请求就成了常见问题之一。本篇攻略将详细介绍如何使用Python Tornado进行跨域请求。 跨域请求 跨域请求是指从一个域的应用中执行JavaScript代码去请求另一…

    Flask 2023年5月15日
    00
  • Flask框架 CSRF 保护实现方法详解

    这是一篇讲解如何在 Flask 框架中实现 CSRF 保护的完整攻略。 什么是 CSRF? CSRF(Cross-site request forgery)是一种攻击技术,攻击者通过伪造一个请求,让用户在未意识到的情况下执行某些操作,比如更改密码、删除数据等。这种攻击方式常常被用于钓鱼、盗取用户信息等恶意行为。 如何在 Flask 中进行 CSRF 保护? …

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