前端互動基礎 – HTML 架構與 DOM 互動
對於習慣寫 Node.js 的你來說,可以這樣理解:HTML 是瀏覽器讀取的資料結構,它定義了介面的「形狀」。
1. 網頁的骨架 – HTML 基礎架構
HTML (HyperText Markup Language) 並不是程式語言,它是一種「標記語言」。如果把網頁想像成一份報紙,HTML 就是用來定義哪裡是標題、哪裡是內文、哪裡是圖片的排版指令。
對於習慣寫 Node.js 的你來說,可以這樣理解:HTML 是瀏覽器讀取的資料結構,它定義了介面的「形狀」。
1.2 HTML 的樹狀結構 (The Tree Structure)
HTML 的核心概念是「巢狀 (Nested)」與「樹狀 (Tree)」。
- 標籤 (Tags):HTML 由
<標籤名>開始,並由</標籤名>結束。 - 父子關係:包在裡面的稱為「子元素 (Child)」,外面的稱為「父元素 (Parent)」。
這種層級關係非常重要,因為之後我們用 JavaScript (DOM) 抓取資料時,往往就是沿著這棵樹在移動。
1.3 標準檔案結構:骨架解析
一個標準的 HTML5 檔案結構非常固定,主要分為三個層次:宣告、頭部 (Head)、身體 (Body)。
完整範例 (index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>我的資料分析儀表板</title>
</head>
<body>
<h1>歡迎來到資料科學課程</h1>
<p>這是一個段落文字。</p>
</body>
</html>1.4 逐行詳細解說
我們將上述代碼拆解來看,每一行都有其存在的意義:
A. 宣告身分
<!DOCTYPE html>- 意義:這不是 HTML 標籤,這是一行「聲明」。
- 作用:它告訴瀏覽器:「請使用最新的 HTML5 標準 來解析這份文件」。如果不寫這行,瀏覽器可能會進入「怪異模式 (Quirks Mode)」,導致排版亂掉。
B. 根元素 (The Root)
<html> ... </html>- 意義:這是整棵樹的「根 (Root)」,所有內容都要包在這裡面。
lang="zh-TW":這是一個屬性,告訴瀏覽器「這個網頁的主要語言是繁體中文」。這對於瀏覽器的翻譯功能和搜尋引擎很重要。
C. 頭部:設定區 (The Head)
<head> ... </head>- 意義:這是網頁的「後台設定」或「腦袋」。
- 特點:寫在這裡的東西絕大部分不會直接顯示在網頁畫面上。
- 關鍵內容:
<meta charset="UTF-8">:非常重要! 這告訴瀏覽器使用 UTF-8 編碼。如果你忘了寫這行,你的中文內容很可能會變成亂碼(尤其是在 Windows 系統上)。<title>...</title>:這是顯示在瀏覽器「分頁標籤」上的文字,也是加入我的最愛時的預設名稱。
D. 身體:顯示區 (The Body)
<body> ... </body>- 意義:這是網頁的「舞台」或「軀幹」。
- 特點:所有使用者看得到的內容(按鈕、圖片、文字、表格)都必須放在這裡面。
- 注意:我們之後寫的 JavaScript
<script>標籤,通常也會放在<body>的最下方(在</body>結束之前),確保網頁內容先跑出來,再執行程式邏輯。
1.5 小結:VS Code 快速指令
如果你使用 VS Code 開發,不需要背誦上述結構。
只要在空的 HTML 檔案中輸入 ! (驚嘆號) 然後按下 Tab 鍵,VS Code 就會自動幫你生成這整套標準骨架。
2. 關鍵元件介紹 – 打造互動介面的積木
在 HTML 的世界裡有上百種標籤,但對於資料科學的互動應用來說,我們不需要花俏的排版,只需要掌握三個核心功能的元件:分組容器、資料輸入、觸發按鈕。
把它們想像成樂高積木,我們將用這三種積木堆疊出使用者的操作介面。
2.1 預備知識:什麼是屬性 (Attributes)?
在介紹元件之前,要先理解「屬性」。HTML 標籤通常長這樣:
<標籤名 屬性="值">
- 標籤名:定義它是什麼(例如:這是一個按鈕)。
- 屬性:定義它的特性(例如:這個按鈕是紅色的、這個輸入框只能填數字)。
2.2 分組容器:<div> (Division)
- 角色:收納盒。
- 用途:
<div>本身沒有任何外觀或功能,它唯一的用途就是「把相關的東西包在一起」。 - 排版特性 (Block Element):
<div>預設是「區塊元素」,意思就是它很霸道,會獨佔一整行。- 當你寫了兩個
<div>,第二個會自動換行跑到下面去。這讓我們可以很輕鬆地把介面切分成「上、中、下」區塊。
應用場景:
我們通常會用一個 <div> 包住「輸入區」,用另一個 <div> 包住「結果顯示區」,讓介面井然有序,不會全部擠在同一行。
<div>
<h3>輸入區</h3>
...
</div>
<div>
<h3>結果區</h3>
...
</div>2.3 資料輸入:<input>
- 角色:數據接口。
- 用途:這是使用者與程式溝通的窗口。
- 語法特性:它是「自我閉合 (Self-closing)」標籤,意思是它沒有結束標籤,寫法是
<input ... >。
關鍵屬性:
type(類型):最重要的屬性,決定輸入框長什麼樣子。type="text":預設值。適合輸入姓名、備註等文字。type="number":資料科學最常用! 瀏覽器會限制只能輸入數字,且手機版會自動彈出數字鍵盤。
placeholder(提示文字):當輸入框是空的時候,顯示灰色的提示字(例如:「請輸入體重...」),使用者一打字就會消失。
<input type="text" placeholder="請輸入姓名">
<input type="number" placeholder="請輸入數值">2.4 觸發按鈕:<button>
- 角色:板機 / 開關。
- 用途:告訴程式「資料填好了,請開始運算」。在我們寫 JavaScript 之前,點它不會有反應,但它是觸發所有邏輯的起點。
- 語法特性:成對標籤,中間夾的文字就是按鈕上顯示的字。
<button>開始分析</button>
<button>清除重填</button>2.5 靈魂屬性:id (身分證字號)
這是這一章節最重要的概念。
HTML 頁面上可能會有 5 個 <input> 和 3 個 <button>,當我們寫 JavaScript 指令說「取得輸入框的值」時,電腦會問:「哪一個輸入框?」
為了精準控制,我們必須給關鍵元素一個獨一無二的代號,這就是 id。
- 規則 1:唯一性。同一個頁面裡,不能有兩個元素叫同一個
id(就像一個班級不能有兩個座號 1 號)。 - 規則 2:命名規範。建議使用英文,不要用空格,單字間可用連字號
-或底線_分隔(例如user-age或btn_submit)。
錯誤示範 vs 正確示範
❌ 錯誤 (JavaScript 會抓錯人):
<input type="number">
<input type="number"> ✅ 正確 (JavaScript 可以精準抓取):
<input type="number" id="input-height">
<input type="number" id="input-weight">
<button id="btn-calc">計算</button>3 組合 – 實作你的第一個互動網頁
現在我們已經認識了所有的積木(HTML 架構、Input、Button、Div),接下來我們要當建築師,把它們組裝起來。
為了讓大家最快上手,我們採用 onclick (點擊事件) 的寫法。這種寫法就像是直接在按鈕上貼一張便利貼,告訴它:「被按的時候,請執行這個動作」。
3.1 建立檔案
請在你的專案資料夾中,建立一個檔案 index.html。
3.2 完整程式碼實作
請將以下代碼完全複製進去。請注意 <button> 標籤裡的 onclick 屬性,以及底下的 <script> 內容。
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>數值判斷器 v1.0</title>
</head>
<body>
<div id="input-section">
<h3>步驟 1:輸入數據</h3>
<p>請輸入一個數值,系統將判斷其大小:</p>
<input type="number" id="data-input" placeholder="例如:100">
<button onclick="runAnalysis()">送出分析</button>
</div>
<hr> <div id="output-section">
<h3>步驟 2:分析結果</h3>
<div id="result-area" style="color: gray; font-weight: bold;">
(等待輸入中...)
</div>
</div>
<script>
// --- JavaScript 邏輯區 ---
// 定義一個函式 (Function),名稱必須跟上面 onclick 設定的一模一樣
function runAnalysis() {
// 1. [抓取元素] 只要抓輸入框(input)和顯示區(div)就好
// (因為按鈕已經用 onclick 綁定了,不需要特別抓它)
const inputEl = document.getElementById('data-input');
const resultEl = document.getElementById('result-area');
// 2. [讀取數值] x + y 的縮寫。
它的意思是:「把 listArea 原本的 HTML 內容拿出來,在後
const rawVal = inputEl.value; // 拿到的是字串
const numVal = Number(rawVal); // 轉成數字
// 3. [運算與判斷]
let message = "";
let textColor = "black";
if (rawVal === "") {
message = "⚠️ 警告:你沒有輸入任何數字!";
textColor = "red";
} else if (numVal > 50) {
message = `📈 數據分析:數值 ${numVal} 大於 50 (高標)`;
textColor = "green";
} else {
message = `📉 數據分析:數值 ${numVal} 小於或等於 50 (低標)`;
textColor = "blue";
}
// 4. [輸出結果] 把文字塞回 HTML
resultEl.textContent = message;
resultEl.style.color = textColor;
}
</script>
</body>
</html>3.4 令一種寫法,用JS綁定點擊按鈕後觸發的方法
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>數值判斷器 v1.0</title>
</head>
<body>
<div id="input-section">
<h3>步驟 1:輸入數據</h3>
<p>請輸入一個數值,系統將判斷其大小:</p>
<input type="number" id="data-input" placeholder="例如:100">
<!-- 注意這裡不同! -->
<button id="submit">送出分析</button>
</div>
<hr> <div id="output-section">
<h3>步驟 2:分析結果</h3>
<div id="result-area" style="color: gray; font-weight: bold;">
(等待輸入中...)
</div>
</div>
<script>
// --- JavaScript 邏輯區 ---
// 定義一個函式 (Function),名稱必須跟上面 onclick 設定的一模一樣
function runAnalysis() {
// 1. [抓取元素] 只要抓輸入框(input)和顯示區(div)就好
// (因為按鈕已經用 onclick 綁定了,不需要特別抓它)
const inputEl = document.getElementById('data-input');
const resultEl = document.getElementById('result-area');
// 2. [讀取數值]
const rawVal = inputEl.value; // 拿到的是字串
const numVal = Number(rawVal); // 轉成數字
// 3. [運算與判斷]
let message = "";
let textColor = "black";
if (rawVal === "") {
message = "⚠️ 警告:你沒有輸入任何數字!";
textColor = "red";
} else if (numVal > 50) {
message = `📈 數據分析:數值 ${numVal} 大於 50 (高標)`;
textColor = "green";
} else {
message = `📉 數據分析:數值 ${numVal} 小於或等於 50 (低標)`;
textColor = "blue";
}
// 4. [輸出結果] 把文字塞回 HTML
resultEl.textContent = message;
resultEl.style.color = textColor;
}
// 注意這裡不同!
let submitEl = document.getElementById('submit');
submitEl.onclick = runAnalysis;
</script>
</body>
</html>4 資料流的處理 – 綜合實作
在 Part 3,我們成功讓網頁「動」了起來。但在處理數據時,我們必須注意資料型別 (Data Types) 的問題,並學習如何用 JavaScript 產生更豐富的結果。
這章節我們將完成一個 BMI 健康分析器。
4.1 新手的惡夢:字串陷阱 (The String Trap)
這是所有學 JavaScript 的人一定會遇到的坑。
當我們使用 document.getElementById('...').value 從 HTML 的 <input> 拿資料時,不管使用者輸入的是不是數字,瀏覽器預設通通都會把它當成「字串 (String)」。
恐怖故事:10 + 10 = ?
如果你寫了這樣的程式碼:
let a = inputA.value; // 假設使用者輸入 10
let b = inputB.value; // 假設使用者輸入 10
let result = a + b;在 Node.js 處理純數字時你會得到 20,但在這裡,你會得到 "1010"!
因為對電腦來說,這是文字的串接,不是數學的加法。
解法:強制轉型
在進行任何運算之前,務必使用 Number() 包裹取回來的值。
// ✅ 正確做法:先轉成數字
let h = Number(inputHeight.value);
let w = Number(inputWeight.value);4.2 綜合實作:BMI 健康分析器 (Mini Project)
讓我們運用目前為止學到的:HTML 架構、onclick 事件、資料轉型,來完成工具。
專案需求
- 輸入:身高(公分)、體重(公斤)。
- 邏輯:
- 將身高換算成公尺(除以 100)。
- 計算 BMI =
kg / (m * m)。 - 取小數點後兩位 (
.toFixed(2))。
- 輸出:顯示 BMI 數值與健康判定。
完整程式碼 (index.html)
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<title>BMI 健康分析器</title>
</head>
<body>
<div>
<h3>BMI 健康計算器</h3>
<p>身高 (cm):</p>
<input type="number" id="height-input" placeholder="例如:175">
<p>體重 (kg):</p>
<input type="number" id="weight-input" placeholder="例如:70">
<br><br>
<button onclick="calcBMI()">開始計算</button>
</div>
<hr>
<div>
<h4>分析報告:</h4>
<div id="result-area">尚未計算</div>
</div>
<script>
function calcBMI() {
// --- A. 抓取與轉型 (Get Data) ---
// 記得!從 input 拿出來的一定要是 Number
const h_input = document.getElementById('height-input').value;
const w_input = document.getElementById('weight-input').value;
// 簡單的防呆:檢查有沒有輸入
if (h_input == "" || w_input == "") {
alert("請輸入完整身高與體重!");
return; // 結束函式,不往下執行
}
const heightCm = Number(h_input);
const weightKg = Number(w_input);
// --- B. 運算邏輯 (Process Data) ---
// 1. 公分轉公尺
const heightM = heightCm / 100;
// 2. 套用公式
const bmiValue = weightKg / (heightM * heightM);
// 3. 取小數點後兩位 (這會變回字串,適合顯示用)
const finalBMI = bmiValue.toFixed(2);
// 4. 判斷體位
let status = "";
if (bmiValue < 18.5) {
status = "體重過輕";
} else if (bmiValue >= 18.5 && bmiValue < 24) {
status = "健康體位";
} else {
status = "體重過重";
}
// --- C. 顯示結果 (Output Data) ---
// 我們使用 innerHTML,這樣可以塞入 <b> 標籤讓重點加粗
const resultDiv = document.getElementById('result-area');
// 使用樣板字串 (Template Literals) 組合 HTML
resultDiv.innerHTML = `
您的 BMI 指數為:<b>${finalBMI}</b> <br>
健康判定:<b>${status}</b>
`;
}
</script>
</body>
</html>4.3 程式碼重點解析
alert(...):這是一個很方便的除錯小工具,會跳出一個瀏覽器視窗警告使用者。.toFixed(2):資料科學常會算出24.123123123這種無限小數,用這個方法可以只保留兩位小數,讓介面更乾淨。innerHTMLvstextContent:- 如果你只用
.textContent,結果出來會是單純的文字。 - 我們這裡用
.innerHTML,是為了能使用<b>...</b>(粗體) 標籤,讓使用者一眼看到重點數字。
- 如果你只用
5: 讓數據留下痕跡 – 列表與輸入重置
目前的 BMI 計算器是一個「一次性」的工具。這章節我們要升級它,讓它具備兩個優化功能:
- 歷史紀錄:把每次算出來的 BMI 往下條列,而不是覆蓋。
- 自動清空:按鈕送出後,自動把輸入框清空,方便輸入下一筆。
5.1 覆蓋 vs. 累加 (Overwrite vs. Append)
這是程式邏輯上的小改變,但對使用者體驗影響巨大。
覆蓋 (
=):resultDiv.innerHTML = "新的結果"舊的內容直接被丟掉。累加 (
+=):resultDiv.innerHTML += "新的結果"原本的內容保留,新的內容接在屁股後面。
5.2 實作:BMI 歷史紀錄器
我們不用修改太複雜的 HTML,只需要多準備一個「容器」來放歷史資料。
完整程式碼 (index.html)
請將這段代碼複製到你的檔案中。
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<title>BMI 歷史紀錄器</title>
</head>
<body>
<div>
<h3>BMI 數據登錄</h3>
<p>身高 (cm):</p>
<input type="number" id="height-input" placeholder="例如:175">
<p>體重 (kg):</p>
<input type="number" id="weight-input" placeholder="例如:70">
<br><br>
<button onclick="addData()">加入紀錄</button>
</div>
<hr>
<div>
<h4>數據紀錄表:</h4>
<ul id="history-list">
</ul>
</div>
<script>
function addData() {
// --- A. 抓取資料 ---
const hInput = document.getElementById('height-input');
const wInput = document.getElementById('weight-input');
// 取得數值
const hVal = Number(hInput.value);
const wVal = Number(wInput.value);
// 防呆檢查
if (hInput.value == "" || wInput.value == "") {
alert("請輸入完整數值!");
return;
}
// --- B. 運算邏輯 ---
const heightM = hVal / 100;
const bmi = (wVal / (heightM * heightM)).toFixed(2);
// --- C. 更新歷史紀錄 (Append Data) ---
const listArea = document.getElementById('history-list');
// 這裡我們使用 += (累加)
// <li> 是列表項目標籤
// 我們把運算結果包成一個 HTML 字串,接在原本內容的後面
listArea.innerHTML += `
<li>
身高: ${hVal}cm / 體重: ${wVal}kg
=> <b>BMI: ${bmi}</b>
</li>
`;
// --- D. 優化體驗:清空輸入框 ---
// 讓使用者不用手動刪除舊數字,可以直接打下一筆
hInput.value = "";
wInput.value = "";
}
</script>
</body>
</html>5.3 程式碼細節解析
A. 清單標籤 <ul> 與 <li>
這是 HTML 專門用來做列表的標籤。
<ul>(Unordered List):列表的外框。<li>(List Item):列表的每一項。- 瀏覽器預設會幫
<li>前面加上一個小黑點(Bullet point),這非常適合用來顯示 Data Log。
B. 魔法運算符 +=
注意看這行:
listArea.innerHTML += `<li>...</li>`;這其實是 x = x + y 的縮寫。
它的意思是:「把 listArea 原本的 HTML 內容拿出來,在後面黏上新的 <li> 字串,然後再塞回去。」
這就是最簡單的動態新增元素方法。
C. 清空輸入框 (Reset)
hInput.value = "";這行看似簡單,卻是 UX(使用者體驗)的關鍵。 在資料科學的資料輸入介面(Data Entry)中,使用者通常會連續輸入多筆資料。如果每次送出後,輸入框還留著上一次的數字,使用者就必須一直按 Backspace 刪除,非常惱人。透過程式自動清空,可以讓輸入流程變得很順暢。