首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

AJAX 分頁查詢實戰:百萬級數據前端分頁與異步加載方案

     編輯:Java 相關知識

場景痛點

  • 查詢返回 10 萬+ 條記錄
  • 原 DataGrid 渲染導致瀏覽器卡死、記憶體飆升
  • 需自研輕量分頁模塊:按需加載、平滑切換、狀態保持

前端 DOM 結構設計

<div id="dataContainer"><!-- 數據列表渲染區 --></div>
<div id="pageNumbers"><!-- 頁碼按鈕組 --></div>
<div id="pageNavigator"><!-- 首頁/上頁/下頁/尾頁/跳轉 --></div>
<div id="pageStatus"><!-- 當前頁/總頁數/總條數 --></div>

核心 JavaScript 分頁邏輯

配置常量

const PAGE_SIZE = 50;      // 每頁條數
const GROUP_SIZE = 7;      // 每組顯示頁碼數
let currentPage = 0;
let totalPages = 0;
let currentGroup = 0;

分組切換:turnGroup(delta)

function turnGroup(delta) {
    // delta: 1=下一組, -1=上一組, 0=首組, -2=尾組
    let startPage;
    switch (delta) {
        case 1:  currentGroup++; startPage = (currentGroup - 1) * GROUP_SIZE + 1; break;
        case -1: currentGroup--; startPage = (currentGroup - 1) * GROUP_SIZE + 1; break;
        case 0:  currentGroup = 1; startPage = 1; break;
        case -2: currentGroup = Math.floor((totalPages - 1) / GROUP_SIZE) + 1;
                 startPage = (currentGroup - 1) * GROUP_SIZE + 1; break;
    }
    renderPageNumbers(startPage);
    renderNavigator();
}

頁面切換:turnPage(pageNo)

async function turnPage(pageNo) {
    if (pageNo === currentPage || pageNo < 1 || pageNo > totalPages) return;

    currentPage = pageNo;
    const rowStart = (pageNo - 1) * PAGE_SIZE + 1;
    const rowEnd = pageNo * PAGE_SIZE;

    // UI 反饋
    document.getElementById('dataContainer').innerHTML = '載入中...';

    try {
        const params = {
            method: 'GetCarTrack',
            sid: '80100117',
            time1: t1,
            time2: t2,
            rowStart,
            rowEnd
        };
        const result = await ajaxPost('MapQuery.ashx', params);
        renderData(result); // 具體渲染邏輯略
    } catch (err) {
        showError(err);
    }

    // 邊界自動翻組
    if (pageNo === 1) turnGroup(0);
    if (pageNo === totalPages) turnGroup(-2);

    document.getElementById('pageStatus').textContent = `第 ${currentPage} 頁 / 共 ${totalPages} 頁`;
}

鍵盤/按鈕導航

function nextPage() {
    if (currentPage < totalPages) {
        turnPage(currentPage + 1);
        if (currentPage > currentGroup * GROUP_SIZE) turnGroup(1);
    }
}
function prevPage() {
    if (currentPage > 1) {
        turnPage(currentPage - 1);
        if (currentPage <= (currentGroup - 1) * GROUP_SIZE) turnGroup(-1);
    }
}

AJAX 封裝:原生 XMLHttpRequest (兼容性最佳)

function ajaxPost(url, params) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('POST', url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    resolve(xhr.responseText); // 或 JSON.parse
                } else {
                    reject(new Error(`HTTP ${xhr.status}`));
                }
            }
        };
        xhr.onerror = () => reject(new Error('Network error'));
        const body = Object.entries(params)
            .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
            .join('&');
        xhr.send(body);
    });
}

後端分頁 SQL:Oracle ROWNUM 方案

-- 查詢第 1-50 條 (第 1 頁)
SELECT * FROM (
    SELECT /*+ FULL(t) */ field1, field2, ROWNUM rn
    FROM big_table t
    WHERE condition
    ORDER BY sort_field DESC
) WHERE rn BETWEEN 1 AND 50;

-- 通用模板: 第 N 頁, 每頁 M 條
SELECT * FROM (
    SELECT cols, ROWNUM rn FROM (
        SELECT cols FROM table WHERE cond ORDER BY sort_col
    ) WHERE ROWNUM <= :endRow
) WHERE rn >= :startRow;

注意:Oracle 12c+ 可用標準 OFFSET ... FETCH NEXT ... ROWS ONLY。

現代化替代方案對比

方案優點缺點適用場景
原生 JS + 模板字符串零依賴、體積極小、完全可控手寫渲染繁瑣、易 XSS極簡頁面、舊專案維護
Vue/React + 分頁組件響應式、組件化、生態豐富引入構建鏈、包體積大現代 SPA 項目
jQuery DataTables / Bootstrap Table功能全 (排序/過濾/導出)、配置式重、難深度定制後台管理系統、快速原型
虛擬滾動 + 無限加載無分頁概念、體驗連貫、大數據友好SEO 難、定位跳轉複雜移動端列表、Feed 流

關鍵優化清單

  • ✅ 後端強制 LIMIT/OFFSET 或 ROWNUM,嚴禁全表查詢再前端切片
  • ✅ 索引覆蓋 WHERE + ORDER BY 列,避免 Filesort
  • ✅ 前端緩存已加載頁面 (Map) 支持秒級回退
  • ✅ 防抖/節流:快速點擊翻頁時合併請求
  • ✅ 骨架屏/加載動畫提升感知性能
  • ✅ 錯誤重試機制 (指數退避)

分頁本質是「空間換時間」:犧牲完整性換取響應速度。百萬級數據下,後端分頁 + 前端異步渲染 + 智能緩存 是經典且有效的工程解法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved