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日

相关文章

  • Django实现简单网页弹出警告代码

    下面是一个详细的攻略,来讲解如何使用Django实现简单网页弹出警告代码。 步骤1:创建一个Django项目 首先,我们需要创建一个Django项目。可以使用以下命令: $ django-admin startproject myproject 步骤2:创建一个Django App 接下来,我们需要创建一个Django App。可以使用以下命令: $ pyt…

    人工智能概论 2023年5月25日
    00
  • spring boot项目中MongoDB的使用方法

    下面就为大家详细讲解Spring Boot项目中MongoDB的使用方法的完整攻略。 1. MongoDB的介绍 MongoDB是一款基于文档模型的NoSQL数据库,它既支持动态模式(BSON),也支持静态模式(JSON),还支持原子操作。MongoDB是一个开源、分布式、高性能的、面向文档的数据库。它旨在提供高性能、高可用性和易扩展性,并通过数据的自动分片…

    人工智能概论 2023年5月25日
    00
  • pytorch实现梯度下降和反向传播图文详细讲解

    下面我会给出一份“pytorch实现梯度下降和反向传播图文详细讲解”的攻略,希望可以帮助到您。 1. 概述 梯度下降是深度学习中常用的优化算法之一,用于更新模型参数从而使得损失函数尽可能小。而反向传播是计算梯度的一种常用方法,用于计算神经网络中所有参数的梯度。本攻略将详细介绍如何使用PyTorch实现梯度下降和反向传播。 2. 梯度下降 在PyTorch中,…

    人工智能概论 2023年5月25日
    00
  • windows10 pycharm下安装pyltp库和加载模型实现语义角色标注的示例代码

    下面是完整的攻略。 1. 确认环境 首先需要确认自己的电脑已经安装过Python和PyCharm,并且配置好了相关环境。同时,LTP语言技术平台也需要被安装在电脑上。 2. 安装pyltp 打开PyCharm,在File -> Settings -> Project: 项目名称 -> Project Interpreter界面中搜索”pyl…

    人工智能概览 2023年5月25日
    00
  • windows下nginx的安装使用及解决80端口被占用nginx不能启动的问题

    下面是Windows下Nginx的安装使用及解决80端口被占用Nginx不能启动的问题的完整攻略。 一、安装Nginx 1.1 下载Nginx 到Nginx官网下载最新版本的Nginx,选择Windows的zip压缩包。 1.2 解压Nginx 将下载好的zip压缩包解压到你想要安装的目录下。 1.3 配置Nginx 打开解压后的Nginx文件夹,找到con…

    人工智能概览 2023年5月25日
    00
  • 宏碁未来蜂鸟轻薄环保电脑怎么样 宏碁未来蜂鸟轻薄环保电脑评测

    宏碁未来蜂鸟轻薄环保电脑评测 宏碁未来蜂鸟轻薄环保电脑是一款采用环保材质设计的轻薄笔记本电脑。它采用了第10代英特尔酷睿处理器、64GB内存和1TB硬盘。在轻薄设计的同时,它不会牺牲性能,让消费者得到了很好的使用体验。 性能 宏碁未来蜂鸟轻薄环保电脑的处理器采用第10代英特尔酷睿处理器,这是目前笔记本电脑市场上性能最优秀的处理器之一。它还配备了64GB内存和…

    人工智能概论 2023年5月25日
    00
  • 深度学习环境搭建anaconda+pycharm+pytorch的方法步骤

    深度学习环境搭建anaconda+pycharm+pytorch的方法步骤 深度学习环境搭建通常需要多个软件工具的配合,在这里我们将介绍使用anaconda+pycharm+pytorch的方法。该环境搭建过程包括三个步骤:安装anaconda、安装pycharm、安装pytorch。 1. 安装anaconda 1.1 下载anaconda:前往anaco…

    人工智能概论 2023年5月25日
    00
  • vscode+platformIO开发stm32f4的实现

    那么让我详细介绍一下如何使用vscode和PlatformIO进行stm32f4的开发。 1. 安装vscode和PlatformIO 要使用vscode和PlatformIO进行stm32f4的开发,你需要先安装这两个工具。 1.1 安装vscode 可以前往官网 https://code.visualstudio.com/ 下载对应的安装包进行安装。 1…

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