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

如何使用Ajax实现页面无刷新自动获取消息?附相关SQL查询代码

如何用Ajax实现无刷新自动获取聊天消息?

嘿,我来帮你搞定这个需求!咱们分后端接口编写和前端Ajax实现两部分来弄,同时还会优化你原代码里的问题(比如SQL注入风险、未读消息范围不准确的问题),一步步来:

1. 后端编写API接口

首先你需要一个后端接口,用来返回当前用户的聊天记录和未读消息数(把两个需求合并成一个接口更高效)。创建一个get_chat.php文件,注意必须修复原代码的SQL注入风险,改用mysqli预处理语句:

<?php
// 数据库连接(假设你已经有合法的$con连接,实际使用时要处理连接错误)
session_start(); 
// 这里假设用户登录后,邮箱存在session中(避免直接通过GET/POST传参被篡改)
$user_email = $_SESSION['logged_in_email'];

// 1. 获取当前用户与管理员的聊天记录(按时间正序返回,方便前端渲染)
$chat_sql = "SELECT * FROM `chat` 
             WHERE (fromthe = ? AND tothe='theadmin') 
             UNION ALL 
             SELECT * FROM `chat` 
             WHERE (fromthe='theadmin' AND tothe=?) 
             ORDER BY id ASC";
$chat_stmt = mysqli_prepare($con, $chat_sql);
mysqli_stmt_bind_param($chat_stmt, "ss", $user_email, $user_email);
mysqli_stmt_execute($chat_stmt);
$chat_result = mysqli_stmt_get_result($chat_stmt);

$chat_messages = [];
while ($row = mysqli_fetch_assoc($chat_result)) {
    $chat_messages[] = $row;
}

// 2. 获取当前用户收到的未读消息数(仅统计管理员发给当前用户的未读消息)
$unread_sql = "SELECT COUNT(*) as unread_count 
               FROM chat 
               WHERE fromthe='theadmin' AND tothe=? AND status=0";
$unread_stmt = mysqli_prepare($con, $unread_sql);
mysqli_stmt_bind_param($unread_stmt, "s", $user_email);
mysqli_stmt_execute($unread_stmt);
$unread_result = mysqli_stmt_get_result($unread_stmt);
$unread_count = mysqli_fetch_assoc($unread_result)['unread_count'];

// 返回JSON格式的响应数据
header('Content-Type: application/json');
echo json_encode([
    'messages' => $chat_messages,
    'unread_count' => $unread_count
]);

// 关闭连接
mysqli_close($con);
?>

注意:你原来的未读消息查询SELECT status FROM chat WHERE status=0太宽泛了,会查询所有用户的未读消息,这里改成了仅统计管理员发给当前用户的未读消息,逻辑更合理。

2. 前端实现Ajax自动请求与渲染

前端需要做两件事:定时请求后端接口获取数据,然后更新聊天区域和未读提示。这里用原生JavaScript实现(无需依赖jQuery,更轻量):

先准备HTML结构

<!-- 聊天消息容器 -->
<div id="chat-container" style="height: 400px; overflow-y: auto; border: 1px solid #eee; padding: 10px;"></div>
<!-- 未读消息提示角标 -->
<div id="unread-badge" style="display: none; background: red; color: white; padding: 2px 6px; border-radius: 50%;">0</div>

然后是JavaScript逻辑

// 获取页面元素
const chatContainer = document.getElementById('chat-container');
const unreadBadge = document.getElementById('unread-badge');
// 定时刷新间隔(3秒一次,可根据需求调整)
const refreshGap = 3000;

// 渲染聊天消息的函数
function renderMessages(messages) {
    // 清空容器(如果想优化性能,可以只添加新消息,这里先做简单实现)
    chatContainer.innerHTML = '';
    messages.forEach(msg => {
        // 判断消息发送者,添加不同样式
        const isAdminMsg = msg.fromthe === 'theadmin';
        const msgClass = isAdminMsg ? 'admin-msg' : 'user-msg';
        const senderName = isAdminMsg ? '管理员' : '我';
        
        const msgElement = document.createElement('div');
        msgElement.className = `chat-item ${msgClass}`;
        msgElement.innerHTML = `
            <div class="sender">${senderName}</div>
            <div class="content">${msg.content}</div>
            <div class="time">${msg.created_at}</div> <!-- 假设你有created_at字段记录消息时间 -->
        `;
        chatContainer.appendChild(msgElement);
    });
    // 自动滚动到最新消息
    chatContainer.scrollTop = chatContainer.scrollHeight;
}

// 更新未读消息提示
function updateUnreadCount(count) {
    if (count > 0) {
        unreadBadge.textContent = count;
        unreadBadge.style.display = 'inline-block';
    } else {
        unreadBadge.style.display = 'none';
    }
}

// 发送Ajax请求获取聊天数据
function fetchChatData() {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', 'get_chat.php', true);
    xhr.onload = function() {
        if (this.status === 200) {
            try {
                const data = JSON.parse(this.responseText);
                renderMessages(data.messages);
                updateUnreadCount(data.unread_count);
            } catch (err) {
                console.error('解析聊天数据失败:', err);
            }
        } else {
            console.error('请求聊天数据失败,状态码:', this.status);
        }
    };
    xhr.onerror = function() {
        console.error('网络请求出错,请检查接口地址');
    };
    xhr.send();
}

// 页面加载时先获取一次数据,之后定时刷新
window.onload = function() {
    fetchChatData();
    setInterval(fetchChatData, refreshGap);
};

3. 可选优化建议

  • 仅加载新消息:不用每次清空重渲染,可以记录最后一条消息的ID,下次请求时只获取ID大于该值的消息,减少数据传输和渲染开销。
  • 标记消息已读:当用户打开聊天页面时,发送Ajax请求调用另一个接口(比如mark_as_read.php),把管理员发给当前用户的未读消息status更新为1。
  • 实时性优化:如果需要更实时的聊天体验,可以用长轮询或者WebSocket替代定时器,减少无效请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:30:38