You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Laravel 5.6.7、Socket.IO和Vue.js实现一对一聊天输入状态提示?

Implementing "User is Typing" Indicator in Laravel 5.6 + Socket.IO + Vue.js

Since you're already using Echo with Socket.IO (no Pusher/Redis), we can extend your existing setup to add typing indicators by creating a new broadcast event and adding frontend logic to detect and handle typing states.

Step 1: Create the Laravel Broadcast Event

First, generate a new event to handle typing status updates:

php artisan make:event UserTypingEvent

Update the event class (app/Events/UserTypingEvent.php) to include the necessary data and broadcast to the correct private channel:

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class UserTypingEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $senderId;
    public $recipientId;
    public $isTyping;

    /**
     * Create a new event instance.
     *
     * @param int $senderId ID of the user who's typing
     * @param int $recipientId ID of the user receiving the typing update
     * @param bool $isTyping Whether the user is typing or stopped
     */
    public function __construct($senderId, $recipientId, $isTyping)
    {
        $this->senderId = $senderId;
        $this->recipientId = $recipientId;
        $this->isTyping = $isTyping;
    }

    /**
     * Define the channel to broadcast on
     * (We send updates to the recipient's private channel)
     */
    public function broadcastOn()
    {
        return new PrivateChannel('Send-Message-Channel.' . $this->recipientId);
    }

    /**
     * Set a clean event name for the frontend to listen for
     */
    public function broadcastAs()
    {
        return 'UserTypingEvent';
    }
}

Ensure your private channel is authorized in routes/channels.php (you likely already have this for your messaging):

Broadcast::channel('Send-Message-Channel.{userId}', function ($user, $userId) {
    // Allow access only if the authenticated user matches the channel's user ID
    return (int) $user->id === (int) $userId;
});

Step 2: Add Frontend Vue.js Logic

Update your Vue component to detect typing, send events, and listen for incoming typing updates.

Update Component Data

Add these properties to track typing states:

data() {
    return {
        message: '',
        typingTimer: null,
        isUserTyping: false,
        otherUserIsTyping: false,
        currentUserId: 1, // Replace with your authenticated user's ID
        recipientId: 2    // Replace with the chat partner's ID
    };
}

Add Input Listener to Message Field

Modify your input field to trigger typing handling:

<input 
    type="text" 
    v-model="message" 
    @input="handleTyping" 
    placeholder="Type your message..."
>

<!-- Typing Indicator -->
<div v-if="otherUserIsTyping" class="typing-indicator">
    {{ otherUserName }} is typing... <!-- Replace with actual user name -->
</div>

Implement Typing Handling Methods

Add these methods to your component:

methods: {
    // Triggered on every input in the message field
    handleTyping() {
        // Send "typing" event if we haven't already
        if (!this.isUserTyping) {
            this.isUserTyping = true;
            this.sendTypingEvent(true);
        }

        // Reset the inactivity timer
        clearTimeout(this.typingTimer);
        // Send "stop typing" after 2 seconds of no input
        this.typingTimer = setTimeout(() => {
            this.isUserTyping = false;
            this.sendTypingEvent(false);
        }, 2000);
    },

    // Send typing status to the server via Socket.IO
    sendTypingEvent(isTyping) {
        const url = "http://localhost:6001/apps/My_appId/events?auth_key=My_Key";
        const socketId = Echo.socketId();
        
        const request = {
            channel: `private-Send-Message-Channel.${this.recipientId}`,
            name: "UserTypingEvent",
            data: {
                senderId: this.currentUserId,
                recipientId: this.recipientId,
                isTyping: isTyping
            },
            socket_id: socketId
        };

        axios.post(url, JSON.stringify(request))
            .catch(error => console.error("Failed to send typing event:", error));
    },

    // Listen for incoming typing events from the chat partner
    listenForTypingEvents() {
        Echo.private(`Send-Message-Channel.${this.currentUserId}`)
            .listen('UserTypingEvent', (event) => {
                // Only update if the sender is our chat partner
                if (event.senderId === this.recipientId) {
                    this.otherUserIsTyping = event.isTyping;
                }
            });
    }
},

// Start listening when the component mounts
mounted() {
    this.listenForTypingEvents();
},

// Clean up timer and send stop typing event when component is destroyed
beforeDestroy() {
    clearTimeout(this.typingTimer);
    if (this.isUserTyping) {
        this.sendTypingEvent(false);
    }
}

Key Notes

  • Replace Placeholder Values: Update currentUserId, recipientId, and otherUserName with actual values from your app (e.g., fetch current user from Laravel Auth, recipient from route props).
  • Adjust Inactivity Timeout: Change the 2000ms (2 seconds) delay to whatever feels natural for your users.
  • Error Handling: The example includes basic error handling for the axios call—you can expand this to show user feedback if needed.

内容的提问来源于stack exchange,提问作者Pankaj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:28:41