当前位置:首页 > 问答 > 正文

用Vuejs咋能实时拿到Redis发来的消息,简单案例分享下

想用Vue.js实时拿到Redis发来的消息,这个事儿光靠Vue.js自己是搞不定的,因为Vue.js是运行在用户浏览器里的前端框架,而Redis是一个躲在服务器深处的内存数据库,它俩根本说不上话,这就像你想让你家的电视(Vue.js)直接收到超市仓库(Redis)的到货通知,中间必须得有个传话的,比如你的手机(后端服务)。

整个流程需要三兄弟一起配合:Redis、一个后端服务(比如用Node.js、Python、Java等写的)、还有咱们的Vue.js前端,核心思路是:后端服务盯着Redis,一旦有新的消息,它就立刻通过一种叫WebSocket的双向通信管道,推给正在浏览器里运行的Vue.js应用,WebSocket不像你平时刷网页那样,只能你问一句它答一句,它建立连接后,服务器可以主动给你发消息,这就完美实现了“实时”。

下面我就用一个超级简单的例子,把这三兄弟怎么配合的给你讲明白,我们假设一个场景:一个简单的聊天室,任何人发送一句话,所有在线的用户都能实时看到。

第一步:后端服务(用Node.js + Socket.IO举例)

你得有个后端来当这个“传话员”,我们选用Node.js和一个非常流行的库叫Socket.IO,它让处理WebSocket变得特别简单,我们需要一个Redis的客户端库来连接Redis。

用Vuejs咋能实时拿到Redis发来的消息,简单案例分享下

  1. 准备工作:在你的Node.js项目里,安装需要的包:npm install socket.io ioredis express(这里用ioredis作为Redis客户端,用express来创建一个简单的HTTP服务器)。
  2. 编写后端代码(比如叫server.js):
const express = require('express');
const http = require('http');
const { createClient } = require('redis');
const { Server } = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
  cors: {
    origin: "*", // 在生产环境中,这里要换成你的Vue.js前端实际域名,用"*"代表允许所有连接,不安全。
    methods: ["GET", "POST"]
  }
});
// 创建Redis客户端并连接
const redisClient = createClient({ host: 'localhost', port: 6379 }); // 根据你的Redis配置修改
(async () => {
  await redisClient.connect();
  console.log('Connected to Redis');
  // 监听Vue前端通过Socket.IO发来的消息
  io.on('connection', (socket) => {
    console.log('一个用户连接上了:', socket.id);
    // 当前端发送 'send-message' 事件时
    socket.on('send-message', async (message) => {
      console.log('收到前端消息:', message);
      // 1. 先把消息存到Redis的一个列表里(比如叫 'chat_messages')
      await redisClient.lPush('chat_messages', JSON.stringify(message));
      // 2. 立刻通过Redis的发布订阅功能,把这个新消息“广播”出去
      await redisClient.publish('chat_channel', JSON.stringify(message));
    });
  });
  // 订阅Redis的 'chat_channel' 频道
  await redisClient.subscribe('chat_channel', (message) => {
    // 当Redis这个频道有新人发消息时,这里就能收到
    console.log('从Redis频道收到消息,准备广播给所有前端:', message);
    // 通过Socket.IO,向所有连接的Vue.js客户端发送一个叫 'new-message' 的事件,并把消息内容带过去
    io.emit('new-message', JSON.parse(message));
  });
})();
server.listen(3000, () => {
  console.log('传话员(后端服务)在3000端口待命!');
});

这段代码干了啥?

  • 开了个WebSocket服务(用Socket.IO)。
  • 连上了Redis。
  • 当有Vue前端连上来,它就等着。
  • 前端发来消息(send-message事件),它就把消息存到Redis列表(可选,为了持久化历史消息),同时通过Redis的发布订阅功能,把消息内容发布到chat_channel频道。
  • 它自己也订阅了chat_channel频道,所以一旦有消息发布到这个频道(其实就是它自己刚发布的),它立马就能收到,收到后,它就通过Socket.IO的io.emit方法,把这个新消息当成一个叫new-message的事件,广播给所有已经连接的Vue.js前端。

第二步:Vue.js前端

现在轮到Vue.js出场了,它需要做两件事:1. 连接到我们刚写的那个后端WebSocket服务;2. 监听后端发来的new-message事件,并把消息显示在页面上。

用Vuejs咋能实时拿到Redis发来的消息,简单案例分享下

  1. 安装Socket.IO客户端库:在Vue.js项目里,npm install socket.io-client
  2. 编写Vue组件(比如叫ChatRoom.vue):
<template>
  <div>
    <h1>简单聊天室</h1>
    <div class="message-list">
      <div v-for="(msg, index) in messages" :key="index" class="message">
        {{ msg.user }}: {{ msg.text }}
      </div>
    </div>
    <div>
      <input v-model="newMessage" @keyup.enter="sendMessage" placeholder="输入消息..." />
      <button @click="sendMessage">发送</button>
    </div>
  </div>
</template>
<script>
import { io } from 'socket.io-client';
export default {
  name: 'ChatRoom',
  data() {
    return {
      messages: [], // 用来存放所有消息的数组
      newMessage: '', // 绑定输入框的消息
      socket: null, // 存放Socket.IO连接实例
    };
  },
  mounted() {
    // 页面加载后,建立到后端服务的WebSocket连接
    // 'http://localhost:3000' 要换成你后端服务实际运行的地址
    this.socket = io('http://localhost:3000');
    // 监听后端发来的 'new-message' 事件
    this.socket.on('new-message', (message) => {
      console.log('从后端收到新消息:', message);
      // 把新消息添加到 messages 数组里,页面就会自动更新显示
      this.messages.unshift(message); // 用unshift加到开头,看起来像最新消息在上方
    });
  },
  methods: {
    sendMessage() {
      if (this.newMessage.trim()) {
        // 构造一个消息对象,可以包含更多信息,比如用户名
        const messageToSend = {
          user: '匿名用户', // 实际应用中这里可能是登录的用户名
          text: this.newMessage,
          timestamp: Date.now()
        };
        // 通过Socket连接,发送一个 'send-message' 事件给后端,并把消息对象带过去
        this.socket.emit('send-message', messageToSend);
        // 清空输入框
        this.newMessage = '';
      }
    }
  },
  beforeUnmount() {
    // 组件销毁前,关闭Socket连接,避免资源泄露
    if (this.socket) {
      this.socket.disconnect();
    }
  }
};
</script>
<style scoped>
.message-list {
  height: 300px;
  border: 1px solid #ccc;
  overflow-y: scroll;
  margin-bottom: 10px;
}
.message {
  padding: 5px;
  border-bottom: 1px dashed #eee;
}
</style>

这段Vue代码干了啥?

  • 在页面加载后(mounted钩子),用socket.io-client库连接到后端服务。
  • 定义了一个sendMessage方法,当用户点击发送或按回车时,它会把输入框的消息通过socket.emit发送给后端(触发后端的send-message事件)。
  • 它一直监听着后端发来的new-message事件(socket.on('new-message')),一旦收到,就把新消息加到本地的messages数组里,Vue的数据响应式特性会自动更新页面,显示这条新消息。

总结一下整个流程:

  1. 用户在Vue.js的输入框打字,点击发送。
  2. Vue.js通过Socket.IO连接,发送send-message事件到Node.js后端。
  3. Node.js后端收到后,将消息存入Redis(可选),并通过Redis的发布订阅功能发布消息。
  4. 同一个Node.js后端因为订阅了那个Redis频道,立刻收到了自己刚发布的消息。
  5. Node.js后端随即通过Socket.IO,向所有连接的Vue.js客户端广播new-message事件。
  6. 所有打开的Vue.js页面(包括发送者自己的页面)都会收到new-message事件,并把新消息实时显示在聊天记录里。

这样,你就用Vue.js实时拿到了从Redis发来的消息,这个例子虽然简单,但清晰地展示了实现实时通信的核心模式,你可以基于这个骨架,去添加更多功能,比如用户登录、消息历史、房间隔离等等。

引用来源说明:以上代码示例和思路是基于WebSocket通信原理、Socket.IO官方文档的基本用法、Redis发布订阅功能以及Vue.js的基础知识综合而成的常见实现方案。