# 標記優先：先把結構講清楚，行為再說

> 設計畫面先用 HTML 把結構描述清楚，行為再疊一層，別從框架元件開始想。HTML attribute 是初始值、DOM property 是執行期狀態，懂這條分界除錯快很多。

原文：https://sheng.page/posts/markup-first-structure-before-behavior/ · 發布：2025-08-16 · 作者：Sheng

我寫一個畫面的時候，習慣先問結構長怎樣，而不是先問要用哪個元件。這順序聽起來小事，但它決定了後面好不好維護、好不好除錯。多數框架教學是反過來教的，先給你一個元件，再叫你把資料塞進去，結構反而被元件的生命週期跟狀態管理糊掉，你最後對「瀏覽器實際渲染出什麼」沒了直覺。

## 先有結構，再包行為

HTML、Markdown、XML 這類標記語言，本質是在描述「這份文件由哪些東西組成、它們的層級關係是什麼」。這是一種宣告式的結構表達，跟「要怎麼做」無關。我偏好讓這層先穩下來：標題就是標題，清單就是清單，表單就是表單，語意對了，無障礙、SEO、可讀性大半就直接拿到。

行為這層應該是輕量包上去的。一個按鈕點下去發一個請求、把回來的片段塞進某個容器，這種互動其實不需要先有一套元件框架。htmx 把這件事做得很俐落，互動寫成 HTML attribute，伺服器主導要回什麼，client 端幾乎不留狀態。我不是說所有東西都該這樣寫，高互動、離線、canvas、local-first 那類應用本來就需要 client 端狀態管理，這沒得避。但對大部分以內容跟表單為主的頁面，預設值該是「結構優先、行為薄一層」，而不是反射性地先架一個 SPA。

當你從 server 回傳的是「一段已經長好的 HTML」，而不是「一包 JSON 再讓 client 重新組 DOM」，心智負擔差很多。前者你打開 devtools 看到什麼就是什麼，後者你得在腦中模擬一遍 render 流程才知道畫面為何長這樣。

## attribute 不是 property

有個區別被框架糊掉很久，但其實很關鍵：HTML attribute 跟 DOM property 不是同一件事。

attribute 是寫在標記裡的初始值，用來描述元素一開始的狀態；瀏覽器解析 HTML、建立 DOM 節點後，節點上的 property 才是執行期間會變動的值。兩者常常同名，內容卻可能分岔。以 `input` 為例，在 HTML 寫下 `value="hello"` 後，使用者輸入新內容會改變 `element.value`，`element.getAttribute("value")` 仍是 `hello`：前者是當下狀態，後者保留初始標記。`checked` 與 `defaultChecked`、`class` 與 `classList` 也有類似分界。

```html
<input value="hello">
<!-- 使用者改成 world 之後 -->
<!-- element.value            => "world"  (DOM property，活的) -->
<!-- element.getAttribute()   => "hello"  (HTML attribute，初始) -->
```

框架的抽象只是把這個分界「減少你直接碰它的機會」，沒有消除它。你在 React 寫 `value={state}`、在別的框架做雙向綁定，底層還是有人在幫你把 property 跟某個狀態源同步。等到哪天綁定行為怪怪的、表單值對不上、第三方套件直接操作 DOM 跟框架打架，你就得回到這個分界去想：現在是 attribute 沒更新，還是 property 被誰偷改了。懂這條線的人，除錯速度差很多，因為他知道該去 inspect 哪一邊。

## 從畫 DOM 樹開始

實務上我會建議，設計一個畫面先在紙上或腦中把 DOM 樹畫出來：根節點是什麼、底下分幾塊、每塊的語意標籤是什麼、哪裡需要可互動。這棵樹畫清楚了，要套什麼框架、要不要拆元件，都是後面的事，而且會變得很自然，因為元件邊界往往就落在樹的自然分界上。

這樣做維護體驗好很多。出問題的時候，你的 mental model 跟 devtools 裡的 Elements 面板是對齊的，你看著真實 DOM 就能往回推；而不是對著一堆元件名稱跟 props，猜它們最後展開成什麼。除錯本質上是在「我以為的結構」跟「實際的結構」之間找落差，這兩者越接近，找落差越快。

還有一個長期觀察。軟體疊得越厚，工具鏈越多層，使用者跟工程師反而會回頭找更薄、更透明的表達方式。純文字、Markdown、各種標記語言之所以耐久，是因為它們可以直接讀、可以 diff、可以丟進版本控制看每一行怎麼變的。一個用十層抽象生出來的畫面，壞掉的時候你很難 diff 出「到底哪一層改了什麼」；一份 HTML 或 Markdown，壞了你一眼就看到。

我偏好結構優先，原因很單純：層級少、責任清楚，結果也直接擺在眼前，不必先跑一遍框架才能理解。這讓畫面更容易控制，也更容易解釋。


## 補充筆記

- 設計畫面先描述結構，再包行為，不要反過來從框架元件開始想。
- HTML attribute 是初始標記狀態，DOM property 是執行期活的狀態，框架只減少、沒消除這條分界。
- 懂 attribute / property 分界的人除錯快，因為知道該 inspect 哪一邊。
- 從畫 DOM 樹開始，mental model 跟 devtools 對齊，找落差就快。
- 軟體越疊越厚，純文字與標記語言因為可讀、可 diff、可版控而更耐久。
> 想法與技術判斷出自 Sheng，和 Claude 一起起草 · 列入 20260613 blog 翻新計劃，新漆未乾。