vue+socket.io+express+mongodb 实现简易多房间在线群聊示例

下面我将详细讲解“vue+socket.io+express+mongodb 实现简易多房间在线群聊示例”的完整攻略,具体步骤如下:

1. 环境准备

在开始编程之前,需要先准备好必要的环境,包括:

  • Node.js及npm包管理器
  • MongoDB数据库
  • Vue.js框架

在确认这些工具已经就绪后,接下来可以开始进行实现了。

2. 服务端实现

本示例中,我们选用了Express作为服务端框架,并集成了Socket.IO作为实现群聊的核心库。

具体实现步骤如下:

2.1. 安装依赖包

首先需要安装相关的依赖包,使用以下命令完成:

npm install --save express socket.io mongodb

2.2. 配置MongoDB数据库

我们需要定义一个数据库模型,来维护用户、房间、聊天记录等相关信息。下面是一个简单的数据模型定义,存储在./models/chat.js中:

const mongoose = require('mongoose');

const ChatSchema = new mongoose.Schema({
  messages: [{
      from: {type: String},
      room: {type: String},
      message: {type: String},
      createdAt: {type: Date, default: Date.now}
  }],
  rooms: [String],  
  users: [String]
}, {
  timestamps: true
});

module.exports = mongoose.model('Chat', ChatSchema);

2.3. 实现服务端代码

以下示例代码实现了服务器端的代码,主要包括:

  • 创建HTTP服务
  • 配置socket.io的事件监听
  • 实现连接、断开连接、发送消息等相关事件监听
const express = require('express');
const app = express();
const server = require('http').createServer(app);

const mongoose = require('mongoose');
const ChatModel = require('./models/chat');
const io = require('socket.io')(server);

let port = 3000;
let host = '127.0.0.1';

let clients = {};
let rooms = [];

mongoose.connect('mongodb://localhost:27017/chatroom', { useNewUrlParser: true, useCreateIndex: true });

const db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB连接错误:'));
db.once('open', () => console.log('MongoDB连接成功!'));

io.on('connection', client => {
  console.log(`[SERVER] ${client.id}已连接`);

  function joinRoom(room) {
    if (rooms.indexOf(room) === -1) {
        rooms.push(room);
    }
    client.join(room);
    clients[client.id].room = room;
    // 发送房间信息给客户端
    io.to(clients[client.id].room).emit('room update', rooms);
    console.log(`[SERVER] ${client.id}进入房间 ${room}`);
  }

  function leaveRoom() {
    let room = clients[client.id].room;
    client.leave(room);
    console.log(`[SERVER] ${client.id}离开房间 ${room}`);
    // 删除空房间 
    if (io.sockets.adapter.rooms[room] === undefined) {
        let index = rooms.indexOf(room);
        rooms.splice(index, 1);
    }
    // 发送房间信息给客户端
    io.emit('room update', rooms);
  }

  client.on('join room', data => {
    if (!clients[client.id]) {
        clients[client.id] = {
            name: data.name,
            room: null
        };
    }
    joinRoom(data.room);
    client.emit('user update', {id: client.id, message: '已加入房间。'});
    client.emit('room joined', data.room);
    client.to(clients[client.id].room).emit('user update', {id: client.id, message: '已进入房间。'});
  });

  client.on('leave room', () => {
    if (!clients[client.id]) {
        return;
    }
    leaveRoom();
    client.emit('user update', {id: client.id, message: '已离开房间。'});
    client.to(clients[client.id].room).emit('user update', {id: client.id, message: '已离开房间。'});
  });

  client.on('disconnect', () => {
    console.log(`[SERVER] ${client.id}已断开连接`);
    if (clients[client.id]) {
        leaveRoom();
        delete clients[client.id];
    }
    io.emit('user update', {id: client.id, message: '已离线。'});
  });

  client.on('message', message => {
    if (clients[client.id]) {
        let data = {
            from: clients[client.id].name,
            room: clients[client.id].room,
            message: message
        };
        // 保存消息记录
        ChatModel.update({}, { $push: { messages: data } }, { upsert: true }, (err) => {
            if (err) {
                console.log(`[SERVER ERROR] ${err}`);
            }
        });
        io.to(clients[client.id].room).emit('message', data);
    }
  });
});

// 启动HTTP服务
server.listen(port, host, () => {
  console.log(`[SERVER] HTTP服务已启动,监听地址为 http://${host}:${port}`);
});

3.客户端实现

我们选用了Vue.js作为客户端框架,使用socket.io-client作为实现群聊的核心库。以下是实现步骤:

3.1. 安装依赖包

首先需要安装相关的依赖包,使用以下命令完成:

npm install --save socket.io-client

3.2. 实现客户端代码

以下示例代码实现了客户端的代码,主要包括:

  • 实现连接、断开连接、发送消息等相关事件监听
  • Vue模板中嵌入socket.io相关事件监听代码
<template>
  <div id="app">
    <header>
      <h1>在线聊天</h1>
    </header>
    <div class="chat-body">
      <div class="chat-room">
        <h5>房间列表({{ rooms.length }})</h5>
        <ul>
          <li v-for="(room, index) in rooms" :key="index" :class="{ active: room === currentRoom }">
            <a @click.prevent="joinRoom(room)">{{ room }}</a>
          </li>
        </ul>
      </div>
      <div class="chat-window">
        <h5>{{ currentRoom }}</h5>
        <ul class="message-list">
          <li v-for="(message, index) in messages" :key="index" :class="{ 'message-own': message.from === username }">
            <div class="username">{{ message.from }} <small>{{ message.createdAt | moment }}</small></div>
            <div class="message">{{ message.message }}</div>
          </li>
        </ul>
        <div class="input-group">
          <input type="text" class="form-control" v-model="message" placeholder="输入消息" @keyup.enter="sendMessage">
          <div class="input-group-append">
            <button class="btn btn-primary" @click.prevent="sendMessage">发送</button>
          </div>
        </div>
      </div>
      <div class="chat-users">
        <h5>用户列表({{ users.length }})</h5>
        <ul>
          <li v-for="(user, index) in users" :key="index">{{ user }}</li>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
import io from 'socket.io-client';

export default {
  name: 'app',

  data () {
    return {
      socket: null,
      currentRoom: null,
      message: '',
      messages: [],
      rooms: [],
      users: [],
      username: null,
    };
  },

  filters: {
    moment(str) {
        return moment(new Date(str)).format("HH:mm:ss");
    },
  },

  created() {
    this.socket = io('http://localhost:3000');
    // 监听socket.io事件 
    this.socket.on('connect', () => {
      console.log(`[CLIENT] connected: ${this.socket.id}`);
    });
    this.socket.on('message', data => {
      console.log(`[CLIENT] message received: ${data.message}`);
      this.messages.push(data);
      this.scrollMessageList();
    });
    this.socket.on('user update', data => {
      console.log(`[CLIENT] user update received: ${JSON.stringify(data)}`);
      this.fetchUsers();
    });
    this.socket.on('room update', data => {
      console.log(`[CLIENT] room update received: ${JSON.stringify(data)}`);
      this.rooms = data;
    });
    this.socket.on('room joined', data => {
      this.currentRoom = data;
      this.fetchMessages();
    });
  },

  mounted() {
    this.username = prompt('请输入您的用户名');
    if (!this.username) {
      alert('用户名不能为空');
      window.location.reload();
    }
    this.fetchRooms();
    this.fetchUsers();
  },

  methods: {
    sendMessage() {
      if (!this.message) {
        return;
      }
      this.socket.emit('message', this.message);
      this.message = '';
    },

    joinRoom(room) {
      this.socket.emit('join room', {
        name: this.username,
        room: room
      });
      this.messages = [];
    },

    fetchMessages() {
      this.messages = [];
      axios.get(`/api/chat/messages/${this.currentRoom}`).then(res => {
        this.messages = res.data[0].messages;
        setTimeout(() => {
          this.scrollMessageList();
        }, 100);
      }).catch(err => {
        console.error(`[CLIENT ERROR] ${err}`);
      });
    },

    fetchRooms() {
      axios.get('/api/chat/rooms').then(res => {
        this.rooms = res.data[0].rooms;
      }).catch(err => {
        console.error(`[CLIENT ERROR] ${err}`);
      });
    },

    fetchUsers() {
      axios.get(`/api/chat/users/${this.currentRoom}`).then(res => {
        this.users = res.data;
      }).catch(err => {
        console.error(`[CLIENT ERROR] ${err}`);
      });
    },

    scrollMessageList() {
        let $messageList = this.$el.querySelector('.message-list');
        $messageList.scrollTop = $messageList.scrollHeight;
    },
  },
};
</script>

<style>
...
</style>

4.完整示例说明

以上就是实现“vue+socket.io+express+mongodb 实现简易多房间在线群聊”示例的全部步骤。具体实现的过程中,需要注意以下几点:

  • 确保服务端和客户端socket.io版本一致
  • 服务端的socket.io要监听客户端的连接事件,客户端要监听与服务端的连接事件
  • 服务端实现socket.io事件响应时,可以根据事件名称实现不同的功能。例如本示例中,message事件是用于处理发送消息,join roomleave room事件用于处理加入和退出房间
  • 客户端实现socket.io事件响应时,可以在Vue模板中嵌入相关代码,例如本示例中,message事件响应代码直接更新messages数组中的内容即可在视图中渲染消息
  • 注意安全问题,例如用户输入的消息、用户名等需要进行合法性验证,防止恶意攻击;同时还要避免在客户端处理不安全的操作,例如Vue模板中嵌入HTML代码等操作

以上就是本示例的完整攻略,希望本次讲解能对您有所帮助!

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue+socket.io+express+mongodb 实现简易多房间在线群聊示例 - Python技术站

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

相关文章

  • pycharm下配置pyqt5的教程(anaconda虚拟环境下+tensorflow)

    下面是在PyCharm中配置PyQt5教程(Anaconda虚拟环境下+tensorflow)的完整攻略: 确认环境 首先,我们需要确保以下环境已经安装: Anaconda(有conda环境管理器) PyCharm(安装了Python插件) TensorFlow(可以通过conda或pip进行安装) 创建conda虚拟环境并安装PyQt5 打开Anacond…

    人工智能概论 2023年5月25日
    00
  • Python集成开发环境Pycharm的使用及技巧

    Python集成开发环境Pycharm的使用及技巧 Pycharm是一款强大的Python集成开发环境,具有代码自动补全、调试、代码质量检查、版本控制等众多功能,提高了Python程序开发的效率。本文将为大家介绍使用Pycharm的基本操作和一些技巧,帮助大家更好地利用这款工具进行Python程序开发。 1. 安装和配置Pycharm 首先我们需要下载和安装…

    人工智能概览 2023年5月25日
    00
  • python实现学员管理系统(面向对象版)

    下面我来详细讲解“Python实现学员管理系统(面向对象版)”的攻略。 系统介绍 本系统基于Python面向对象编程实现,能够实现对学员的管理,包括添加学员、删除学员、查看学员列表、修改学员信息等功能。本系统采用了文本文件存储数据的方法,每个学员的信息都存储在一个独立的文本文件中。 系统功能 本系统实现了如下功能: 添加学员信息; 删除学员信息; 修改学员信…

    人工智能概览 2023年5月25日
    00
  • vscode debug怎么用? vscode配置使用debug的技巧

    VS Code Debug 怎么用? VS Code 的 Debug 功能可以帮助开发者快速定位代码错误并进行调试,以下是 VS Code Debug 的使用攻略: 步骤一:在 VS Code 中打开代码目录 在打开的文件夹下,找到要调试的代码文件,并在文件顶部或侧边栏末尾找到调试按钮。点击按钮选择“添加配置”选项。 步骤二:选择 Debugger 在选择 …

    人工智能概论 2023年5月25日
    00
  • Python打造出适合自己的定制化Eclipse IDE

    Python打造出适合自己的定制化Eclipse IDE攻略 背景 Eclipse IDE 是最流行的集成开发环境之一。Eclipse提供了针对不同编程语言的插件,例如Java、C++、PHP等等。但是,在进行特定类型的软件开发时,可能需要添加更多自定义插件或者修改现有的插件。本文将介绍如何使用Python定制Eclipse IDE以满足特定开发需求。 步骤…

    人工智能概论 2023年5月25日
    00
  • Django中redis的使用方法(包括安装、配置、启动)

    下面是Django中redis的使用方法的完整攻略。 安装redis 首先需要安装redis服务器。具体的安装过程依赖于你的操作系统。以下是在Ubuntu系统上安装的步骤: 打开终端程序,使用以下命令更新Ubuntu安装源: sudo apt-get update 使用以下命令安装redis: sudo apt-get install redis-serve…

    人工智能概论 2023年5月25日
    00
  • Python一行代码识别发票并保存Excel示例详解

    下面是关于“Python一行代码识别发票并保存Excel示例详解”这个主题的详细讲解攻略。 一、概述 这篇文章主要介绍了如何使用Python代码识别发票信息并保存到Excel中。使用OCR技术识别出图片中的文字,并使用正则表达式进行匹配提取出发票的相关信息,最后将提取出的信息保存到Excel文件中。 二、实现步骤 1. 安装依赖包 使用Python代码处理图…

    人工智能概论 2023年5月25日
    00
  • Django应用程序中如何发送电子邮件详解

    Django应用程序通过使用内置的Python库和第三方库可以轻松地发送电子邮件。本攻略将详细讲解Django应用程序中如何使用邮件功能。 安装依赖库 在使用邮件功能之前,需要安装两个包:django和django-environ。 可以使用以下命令安装它们: pip install django pip install django-environ 在se…

    人工智能概览 2023年5月25日
    00
合作推广
合作推广
分享本页
返回顶部