三級聯動 (如省市區、商品分類) 是表單常見需求。本文提供資料庫設計、後端 API (get2.php)、前端頁面 (index.php + aa.js) 完整可運作代碼,採用原生 XMLHttpRequest (相容舊瀏覽器),並說明現代 Fetch/axios 重構方向。
CREATE TABLE `area` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(50) NOT NULL COMMENT '名稱',
`parent_id` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '父級 ID,0 為頂級',
`level` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '層級 1/2/3',
`sort` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '排序',
INDEX `idx_parent` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 示例資料
INSERT INTO `area` (`id`,`name`,`parent_id`,`level`) VALUES
(1, '台灣', 0, 1),
(2, '台北市', 1, 2), (3, '新北市', 1, 2), (4, '桃園市', 1, 2),
(5, '中正區', 2, 3), (6, '大同區', 2, 3), (7, '板橋區', 3, 3), (8, '中壢區', 4, 3);
prepare("SELECT id, name FROM area WHERE parent_id = ? ORDER BY sort, id");
$stmt->execute([$parentId]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['code' => 0, 'data' => $rows]);
三級聯動示例
地區選擇
// js/cascade-legacy.js
function createXHR() {
if (window.XMLHttpRequest) return new XMLHttpRequest();
try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
return null;
}
function loadLevelLegacy(level, parentId) {
const xhr = createXHR();
if (!xhr) return alert('瀏覽器不支援 AJAX');
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 0)) {
const res = JSON.parse(xhr.responseText);
const sel = document.getElementById('level' + level);
sel.innerHTML = '';
res.data.forEach(item => {
const opt = document.createElement('option');
opt.value = item.id; opt.textContent = item.name;
sel.appendChild(opt);
});
sel.disabled = false;
}
};
xhr.open('GET', 'api/area.php?parent_id=' + parentId, true);
xhr.send(null);
}
| 方向 | 做法 |
|---|---|
| 前端框架 | Vue/React 元件化 <CascadeSelect :levels="3" :api="/api/area" /> |
| 資料預載 | 首屏直出 JSON 注入 window.__INITIAL_DATA__,避免首屏 AJAX 等待 |
| 虛擬滾動 | 選項超過 500 時使用虛擬列表 (react-window/vue-virtual-scroller) |
| 搜尋過濾 | Select2 / TomSelect / 下拉輸入框支援關鍵字過濾 |
| 快取策略 | 第一級資料極少變動,可 localStorage/IndexedDB 快取,離線可用 |
| API 規範 | RESTful: GET /api/areas?parent_id=1,回傳標準 {code, data, message} |
parent_id 傳遞正確、資料表有對應子資料、JS 選取器 ID 正確。Access-Control-Allow-Origin)。