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

PHP + JavaScript 實作三級下拉選單聯動完整教學

     編輯:PHP 相關知識

從資料庫讀取資料,打造動態三級選單聯動效果

本文示範如何結合 PHP 後端與 JavaScript 前端,從 MySQL 資料庫讀取分類資料,實作三級下拉選單聯動(省/市/區、分類/子分類/品牌等常見場景),包含遞迴樹狀選單與 AJAX 非同步載入兩種架構。

資料庫結構設計

CREATE TABLE `menu` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(50) NOT NULL COMMENT '選單名稱',
  `parent_id` INT DEFAULT 0 COMMENT '父層 ID,0 為頂層',
  `url` VARCHAR(255) DEFAULT '' COMMENT '連結網址',
  `sort` INT DEFAULT 0 COMMENT '排序權重'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

核心實作:遞迴樹狀選單 (PHP + JS)

這個版本一次載入所有資料,透過 PHP 遞迴產生巢狀 HTML,再用 JS 控制展開/收合。

PHP 遞迴函式產生選單

<?php
function showTreeMenu($conn, $result, $layer = 1) {
    $numRows = mysqli_num_rows($result);
    if ($numRows === 0) return;

    echo "";
    while ($row = mysqli_fetch_assoc($result)) {
        // 取得子選單
        $subSql = "SELECT * FROM menu WHERE parent_id = {$row['id']}";
        $subResult = mysqli_query($conn, $subSql);
        $hasChildren = mysqli_num_rows($subResult) > 0;

        echo "";
        // 展開/收合圖示
        if ($hasChildren) {
            echo "";
            echo "";
        } else {
            echo "";
            echo "";
        }
        echo "";

        // 遞迴輸出子選單
        if ($hasChildren) {
            $GLOBALS['menuId']++;
            echo "";
        }
    }
    echo "
"; } // 主程式 $conn = mysqli_connect("localhost", "root", "123456", "menu"); mysqli_set_charset($conn, "utf8"); $GLOBALS['menuId'] = 1; $sql = "SELECT * FROM menu WHERE parent_id = 0"; $result = mysqli_query($conn, $sql); showTreeMenu($conn, $result); ?>

JavaScript 控制展開/收合

<script>
function showMenu(menuId) {
    const el = document.getElementById(menuId);
    if (el) el.style.display = (el.style.display === 'none') ? '' : 'none';
}
</script>

進階架構:AJAX 非同步載入 (推薦大量資料)

避免一次載入龐大資料,改為使用者點選時才向後端請求下一層資料。

前端 HTML + JS (jQuery 範例)

<select id="level1" name="level1"></select>
<select id="level2" name="level2" disabled></select>
<select id="level3" name="level3" disabled></select>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$('#level1').on('change', function() {
    const val = $(this).val();
    $('#level2, #level3').html('').prop('disabled', true);
    if (!val) return;
    $.getJSON('api_get_children.php', {parent_id: val}, function(data) {
        $.each(data, function(i, item) {
            $('#level2').append(``);
        });
        $('#level2').prop('disabled', false);
    });
});

$('#level2').on('change', function() {
    const val = $(this).val();
    $('#level3').html('').prop('disabled', true);
    if (!val) return;
    $.getJSON('api_get_children.php', {parent_id: val}, function(data) {
        $.each(data, function(i, item) {
            $('#level3').append(``);
        });
        $('#level3').prop('disabled', false);
    });
});
</script>

後端 API (api_get_children.php)

<?php
header('Content-Type: application/json; charset=utf-8');
$conn = mysqli_connect("localhost", "root", "123456", "menu");
mysqli_set_charset($conn, "utf8");

$parentId = isset($_GET['parent_id']) ? (int)$_GET['parent_id'] : 0;
$sql = "SELECT id, name FROM menu WHERE parent_id = $parentId ORDER BY sort";
$result = mysqli_query($conn, $sql);

$data = [];
while ($row = mysqli_fetch_assoc($result)) {
    $data[] = $row;
}
echo json_encode($data, JSON_UNESCAPED_UNICODE);
?>

效能優化與最佳實踐

  1. 索引優化:`parent_id` 欄位務必加索引。
  2. 快取策略:頂層選單資料極少變動,建議用 Redis 或檔案快取,減少 DB 查詢。
  3. 無限分類:遞迴函式支援 N 層,不限三級,資料表結構不變。
  4. 前端框架整合:Vue/React 專案建議改用元件化開發,搭配遞迴元件。
  5. 無障礙支援:加上 `aria-expanded`、`role="treeitem"` 等屬性。

常見問題排查

  • 選單不顯示:檢查 JS 錯誤、資料庫連線、SQL 語法、編碼是否為 UTF-8。
  • 中文亂碼:確認資料表、連線、頁面、JSON 輸出皆為 UTF-8。
  • 效能慢:資料量大時改用 AJAX 分層載入,或一次性載入改用 JSON 傳給前端渲染。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved