原生 JavaScript 實作 Tab 功能選單筆記

前言

Tab 功能是前端常見的 UI 元件,許多框架都提供現成的實作,但若想深入理解其背後的運作原理,使用原生 JavaScript 自行實作是一個很好的練習。本文適合有基礎程式能力的工程師或自學者,透過範例拆解,了解如何控制元素顯示與切換樣式。

HTML 結構說明

Tab 功能主要由兩部分組成:控制按鈕與內容區塊。

  • 按鈕部分使用 <a> 標籤,href="javascript:void(0)" 用來阻止預設跳轉行為。
  • 按鈕會帶有 tablink 及特定的 testbtn class,方便 JavaScript 操作。
  • onclick 事件會呼叫 openClass(event, 'classX'),帶入事件物件與對應內容區塊的 id。
  • 內容區塊以 idclass="class" 標示,對應按鈕的參數,方便顯示與隱藏。
<div class="bar-block">
  <div class="container">

<h5>選單</h5>
    <a href="javascript:void(0)" class="bar-item button tablink testbtn" onclick="openClass(event, 'class1')">教學1</a>
    <a href="javascript:void(0)" class="bar-item button tablink" onclick="openClass(event, 'class2')">教學2</a>
    <a href="javascript:void(0)" class="bar-item button tablink" onclick="openClass(event, 'class3')">教學3</a>
    <a href="javascript:void(0)" class="bar-item button tablink" onclick="openClass(event, 'class4')">教學4</a>
  </div>
</div>

<div id="class1" class="container class">
  教學1內容
</div>
<div id="class2" class="container class">
  教學2內容
</div>
<div id="class3" class="container class">
  教學3內容
</div>
<div id="class4" class="container class">
  教學4內容
</div>

JavaScript 功能解析

openClass 函式負責切換 Tab 的顯示狀態與按鈕樣式:

  1. 使用 document.getElementsByClassName("class") 取得所有內容區塊,並將它們隱藏(display = "none")。
  2. 取得所有按鈕元素 tablinks,並移除所有按鈕的 red 樣式,確保只有一個按鈕被標示為選中。
  3. 根據傳入的 className 參數,將對應內容區塊顯示(display = "block")。
  4. 對當前點擊的按鈕元素新增 red class,標示為選中狀態。
function openClass(evt, className) {
  var i, x, tablinks;
  x = document.getElementsByClassName("class");
  for (i = 0; i < x.length; i++) {
    x[i].style.display = "none";
  }
  tablinks = document.getElementsByClassName("tablink");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].classList.remove("red");
  }
  document.getElementById(className).style.display = "block";
  evt.currentTarget.classList.add("red");
}

// 頁面載入後自動觸發第一個帶有 testbtn 的按鈕點擊
var mybtn = document.getElementsByClassName("testbtn")[0];
mybtn.click();

實際應用與延伸

  • 可依需求調整 red class 的 CSS 樣式,達到不同的選中效果。
  • 若 Tab 數量動態產生,需確保事件綁定正確。
  • 可改用事件代理方式優化效能。
  • 進階可結合動畫效果,提升使用者體驗。

常見坑點

  • 忘記阻止 <a> 的預設行為會導致頁面跳轉。
  • 未正確移除其他按鈕的選中樣式,導致多個 Tab 同時被標示。
  • 忘記預設觸發第一個 Tab,頁面初始狀態會空白。

完整程式碼

<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<title>原生 JavaScript Tab 功能</title>
<style>
  .red { color: red; font-weight: bold; }
  .class { display: none; }
</style>
</head>
<body>

<div class="bar-block">
  <div class="container">

<h5>選單</h5>
    <a href="javascript:void(0)" class="bar-item button tablink testbtn" onclick="openClass(event, 'class1')">教學1</a>
    <a href="javascript:void(0)" class="bar-item button tablink" onclick="openClass(event, 'class2')">教學2</a>
    <a href="javascript:void(0)" class="bar-item button tablink" onclick="openClass(event, 'class3')">教學3</a>
    <a href="javascript:void(0)" class="bar-item button tablink" onclick="openClass(event, 'class4')">教學4</a>
  </div>
</div>

<div id="class1" class="container class">
  教學1內容
</div>
<div id="class2" class="container class">
  教學2內容
</div>
<div id="class3" class="container class">
  教學3內容
</div>
<div id="class4" class="container class">
  教學4內容
</div>

<script>
function openClass(evt, className) {
  var i, x, tablinks;
  x = document.getElementsByClassName("class");
  for (i = 0; i < x.length; i++) {
    x[i].style.display = "none";
  }
  tablinks = document.getElementsByClassName("tablink");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].classList.remove("red");
  }
  document.getElementById(className).style.display = "block";
  evt.currentTarget.classList.add("red");
}

var mybtn = document.getElementsByClassName("testbtn")[0];
mybtn.click();
</script>

</body>
</html>