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

PHP + JS + AJAX + MySQL 實現省市三級聯動下拉選單完整實戰

     編輯:PHP 綜合知識

三級聯動(省→市→區/縣)是表單設計常見需求。本文提供基於 PHP + MySQL + 原生 AJAX (XMLHttpRequest) + DOM 操作的完整實現,無依賴第三方庫。

資料庫設計

CREATE TABLE `areas` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `parent_id` int(11) DEFAULT 0, -- 0=省級, 省id=市級, 市id=區級
  `level` tinyint(1) DEFAULT 1,  -- 1=省, 2=市, 3=區
  PRIMARY KEY (`id`),
  KEY `parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

後端 API:ajax-area-server.php

<?php
header('Content-Type: application/json; charset=utf-8');
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'root', '');

$parentId = isset($_GET['parent_id']) ? (int)$_GET['parent_id'] : 0;
$stmt = $pdo->prepare('SELECT id, name FROM areas WHERE parent_id = ? ORDER BY id');
$stmt->execute([$parentId]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

echo json_encode(['code' => 200, 'data' => $rows]);
?>

前端頁面:ajax-area-select.html

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>三級聯動</title></head><body>
<select id="province" onchange="loadChildren(this.value, 'city')"></select> 省
<select id="city" onchange="loadChildren(this.value, 'district')"></select> 市
<select id="district"></select> 區/縣

<script>
function loadChildren(parentId, targetSelectId) {
    const target = document.getElementById(targetSelectId);
    // 清空現有選項
    target.innerHTML = '<option value="0">-- 請選擇 --</option>';
    // 重置下級選單
    if (targetSelectId === 'city') {
        document.getElementById('district').innerHTML = '<option value="0">-- 請選擇 --</option>';
    }
    if (!parentId) return;

    // AJAX 請求
    const xhr = new XMLHttpRequest();
    xhr.open('GET', `ajax-area-server.php?parent_id=${parentId}`, true);
    xhr.onload = function() {
        if (xhr.status === 200) {
            const resp = JSON.parse(xhr.responseText);
            if (resp.code === 200) {
                resp.data.forEach(item => {
                    const opt = document.createElement('option');
                    opt.value = item.id;
                    opt.textContent = item.name;
                    target.appendChild(opt);
                });
            }
        }
    };
    xhr.send();
}

// 頁面載入時初始化省份
window.onload = function() {
    loadChildren(0, 'province');
};
</script>
</body></html>

jQuery 簡化版 (可選)

<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<script>
function loadChildren(parentId, targetId) {
    const $target = $('#' + targetId);
    $target.html('<option value="0">-- 請選擇 --</option>');
    if (!parentId) return;
    $.getJSON('ajax-area-server.php', {parent_id: parentId}, function(resp) {
        if (resp.code === 200) {
            $.each(resp.data, function(i, item) {
                $target.append(`<option value="${item.id}">${item.name}</option>`);
            });
        }
    });
}
</script>

效能優化建議

  1. 前端快取:省份資料極少變動,可 localStorage 快取
  2. 防抖處理:快速切換時取消前一請求 xhr.abort()
  3. 索引優化:parent_id 欄位必須加索引
  4. 分頁/虛擬滾動:單級選項超過 500 考慮分組或搜尋框

安全考量

  • 後端驗證 parent_id 合法性,防止注入
  • 輸出 JSON 時設定 Content-Type: application/json
  • 生產環境啟用 HTTPS,防止中間人竄改選項

此架構前後端分離清晰,易於擴展為 RESTful API、支援多語言、整合 Vue/React 等現代框架。

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