如何为Vue.js配置Server-Sent Events?及竞价应用的Vue+Express实现
Hey there! Let's tackle your two Server-Sent Events questions one by one—first getting SSE set up with Vue.js, then implementing the real-time bid updates for your auction app.
Setting up SSE in Vue is straightforward—you'll create a persistent connection to your Express SSE endpoint directly in your component, then handle incoming events. Here's a practical implementation:
Establish the SSE connection in your component:
Use themounted()hook to initialize the connection after the component renders, and clean it up when the component is destroyed to avoid lingering connections.export default { data() { return { eventSource: null, // Add your other data properties here }; }, mounted() { // Replace with your actual Express SSE endpoint URL this.eventSource = new EventSource('http://localhost:3000/sse'); // Listen for generic SSE messages this.eventSource.onmessage = (event) => { const data = JSON.parse(event.data); console.log('Received SSE update:', data); // Handle the data update logic here }; // Add error handling to auto-reconnect if the connection drops this.eventSource.onerror = (error) => { console.error('SSE connection error:', error); setTimeout(() => this.mounted(), 5000); // Retry after 5 seconds }; }, beforeUnmount() { // Close the connection when the component is removed if (this.eventSource) { this.eventSource.close(); } } };Quick tips:
EventSourceis a native browser API—no extra npm packages are required (unless you need polyfills for older browsers).- Always clean up the connection in
beforeUnmount()to prevent memory leaks.
For your bidding system, we'll build two core parts: an Express server that broadcasts bid updates via SSE, and a Vue component that listens for these updates to refresh the correct auction item.
Express.js Server Setup
First, create an SSE endpoint to track connected clients, and trigger broadcasts whenever a maximumBid is updated in your backend.
- Set up SSE tracking and broadcast logic:
const express = require('express'); const app = express(); const cors = require('cors'); // Use this if your Vue app runs on a different port app.use(cors()); app.use(express.json()); // Store active SSE connections (for production, use Redis or a pub/sub system for scaling) const sseClients = []; // SSE endpoint app.get('/sse', (req, res) => { // Set required SSE headers res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.setHeader('Access-Control-Allow-Origin', '*'); // Restrict to your Vue app's origin in production // Send an initial welcome message res.write('event: welcome\ndata: Connected to auction updates\n\n'); // Add the client to our active connections list sseClients.push(res); // Remove the client when their connection closes req.on('close', () => { const index = sseClients.indexOf(res); if (index !== -1) { sseClients.splice(index, 1); } }); }); // Example route for handling bid submissions (replace with your existing bid logic) app.post('/submit-bid', async (req, res) => { const { itemId, newBid } = req.body; // 1. Update your database with the new maximumBid // const updatedItem = await AuctionItem.findByIdAndUpdate(itemId, { maximumBid: newBid }, { new: true }); const updatedItem = { id: itemId, maximumBid: newBid /* Include other item fields here */ }; // Replace with your actual DB response // 2. Broadcast the update to all connected SSE clients const updatePayload = JSON.stringify(updatedItem); sseClients.forEach(client => { client.write(`event: bidUpdate\ndata: ${updatePayload}\n\n`); }); res.json({ success: true, item: updatedItem }); }); app.listen(3000, () => console.log('Server running on port 3000'));
Vue Component Setup
Adjust your auction component to listen for the custom bidUpdate event and update the correct item in your auctionedItems array:
<template> <div v-for="item in auctionedItems" :key="item.id"> <Item :info="item"></Item> </div> </template> <script> import Item from './Item.vue'; export default { components: { Item }, data() { return { auctionedItems: [], eventSource: null }; }, async mounted() { // 1. Fetch initial auction items from your Express API const response = await fetch('http://localhost:3000/auction-items'); this.auctionedItems = await response.json(); // 2. Initialize SSE connection this.eventSource = new EventSource('http://localhost:3000/sse'); // Listen for the custom 'bidUpdate' event this.eventSource.addEventListener('bidUpdate', (event) => { const updatedItem = JSON.parse(event.data); // Find the matching item in our array and update it const itemIndex = this.auctionedItems.findIndex(item => item.id === updatedItem.id); if (itemIndex !== -1) { // Use Vue's reactivity system by replacing the item (don't mutate directly) this.auctionedItems.splice(itemIndex, 1, { ...this.auctionedItems[itemIndex], ...updatedItem }); } }); // Handle SSE connection errors and retry this.eventSource.onerror = (error) => { console.error('SSE connection failed:', error); setTimeout(() => this.mounted(), 5000); }; }, beforeUnmount() { if (this.eventSource) { this.eventSource.close(); } } }; </script>
- Key Vue notes:
- Using
addEventListener('bidUpdate')keeps your code organized if you add more SSE event types later. - Replacing the item in the array (instead of mutating it directly) ensures Vue's reactivity system triggers a re-render for the updated item.
- Using
内容的提问来源于stack exchange,提问作者maikelinhas

