iT邦幫忙

2026 iThome 鐵人賽

DAY 11
0
JavaScript

React 觀念架構:從js 基礎到Hook 底層邏輯 系列 第 11 篇

Day 11 命令式 vs. 聲明式:從 DOM 操作轉變為「UI 是 State 的函數」

  • 分享至 

  • xImage
  •  

一、 命令式 (Imperative) vs. 聲明式 (Declarative)

簡單來說,兩種範式的核心差異在於:

  • 命令式(How):關注「一步步如何做」。你需要親自告訴電腦每一個操作步驟、如何選取 DOM 節點、如何監聽事件以及如何修改畫面。

  • 聲明式(What):關注「結果是什麼」。你只需要描述當前狀態下「畫面應該長什麼樣子」,至於如何把 DOM 變成那個樣子,全部交由 React 處理。

生活中的比喻:點一杯咖啡

  • 命令式:「請拿一個紙盃,裝入兩份濃縮咖啡,接著蒸熱牛奶到 65 度,慢慢倒進杯子裡,最後在表面拉一個心形花紋。」

  • 聲明式:「請給我一杯熱拿鐵。」

二、 程式碼比對:製作一個「按鈕切換展開/折疊」選單

  1. 傳統命令式寫法 (原生 JS / jQuery)
    你需要手動尋找節點、添加事件,並根據當前狀態手動切換 CSS Class 或 DOM 結構:
// 命令式:步驟繁瑣,狀態與 DOM 強烈耦合
const button = document.querySelector('#toggle-btn');
const content = document.querySelector('#content');

let isOpen = false;

button.addEventListener('click', () => {
  isOpen = !isOpen;
  if (isOpen) {
    content.style.display = 'block';
    button.textContent = '收起內容';
  } else {
    content.style.display = 'none';
    button.textContent = '展開內容';
  }
});

問題:隨著 UI 變得複雜(例如有多個狀態交織:載入中、錯誤、已登入、無權限),手動維護 DOM 狀態會迅速演變成混亂的蛛網,極易產生 UI 與實際資料不一致的 Bug。

  1. React 聲明式寫法
    你只需專注於定義 State(狀態),並根據 State 描述 UI:
// 聲明式:UI 單純是 State 的映射結果
function ToggleMenu() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>
        {isOpen ? '收起內容' : '展開內容'}
      </button>
      {isOpen && <div className="content">這是展開的內容</div>}
    </div>
  );
}`

三、 轉變三大法則

  1. 忘掉 DOM 選取器:不要再寫 document.getElementById 或 querySelector。如果需要改變畫面,先思考「我需要什麼 State?」。

  2. 讓資料驅動 UI:把 UI 視為資料狀態的「結果」。狀態對了,畫面自然就會對。

  3. 收斂狀態數量:盡量只維護「最小可變狀態」,衍生資料(如計算總價、篩選列表)應在渲染時直接計算,避免產生冗餘的 State。


上一篇
Day 10 Diffing Algorithm 拆解:為什麼列表渲染要給 key?
下一篇
Day 12 Component Render 生命週期:觸發 Re-render 的三大時機
系列文
React 觀念架構:從js 基礎到Hook 底層邏輯 共 14 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言