You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/zh-TW/7-bank-project/1-template-route
localizeflow[bot] a5481015bd
chore(i18n): sync translations with latest source changes (chunk 2/2, 261 changes)
7 months ago
..
README.md chore(i18n): sync translations with latest source changes (chunk 2/2, 261 changes) 7 months ago
assignment.md chore(i18n): sync translations with latest source changes (chunk 2/2, 261 changes) 7 months ago

README.md

建立銀行應用程式 第一部分HTML 模板與網頁應用程式中的路由

journey
    title 您的銀行應用程式開發旅程
    section SPA 基礎
      了解單頁應用程式: 3: 學生
      學習模板概念: 4: 學生
      精通 DOM 操作: 4: 學生
    section 路由系統
      實作客戶端路由: 4: 學生
      處理瀏覽器歷史紀錄: 5: 學生
      建立導航系統: 5: 學生
    section 專業模式
      建立模組化架構: 5: 學生
      應用最佳實務: 5: 學生
      創建使用者體驗: 5: 學生

當阿波羅11號在1969年登月時其導航電腦必須在不同程式間切換卻不需重新啟動整個系統。現代網頁應用程式也類似 — 它們改變你所看到的內容,而非重新載入全部,這讓用戶體驗變得流暢且反應迅速。

不同於傳統網站每次互動都會重新載入整頁,現代網頁應用程式只更新需要改變的部分。這種作法就像任務控制中心在切換不同顯示畫面,同時保持持續通訊,帶來我們所期望的流暢體驗。

使差異如此顯著的原因如下:

傳統多頁應用程式 現代單頁應用程式
導覽 每個畫面重新載入整頁
效能 因為完整HTML下載較慢
用戶體驗 頁面閃爍令人分心
資料共享 頁面間共享困難
開發 需維護多個HTML文件

理解演變歷程:

  • 傳統應用程式 每次導覽都需要向伺服器發送請求
  • 現代SPA 一次載入即可利用JavaScript動態更新內容
  • 用戶期望 現在偏好即時無縫的互動體驗
  • 效能優勢 包含降低頻寬使用與加快回應速度

在本課程中我們將建立一個銀行應用程式有多個畫面並且流暢銜接。就像科學家使用可模組化的儀器可依需求重新組合我們將用HTML模板作為可重複使用的元件必要時顯示。

你會操作HTML模板用於不同畫面重複使用的藍圖、JavaScript路由系統負責畫面切換、以及瀏覽器歷史API讓返回按鈕如預期運作。這些就是React、Vue、Angular等框架背後的基本技術。

最後,你將擁有一個功能完整且展現專業單頁應用原則的銀行應用程式。

mindmap
  root((單頁應用程式))
    Architecture
      Template System
      Client-side Routing
      State Management
      Event Handling
    Templates
      Reusable Components
      Dynamic Content
      DOM Manipulation
      Content Switching
    Routing
      URL Management
      History API
      Navigation Logic
      Browser Integration
    User Experience
      Fast Navigation
      Smooth Transitions
      Consistent State
      Modern Interactions
    Performance
      Reduced Server Requests
      Faster Page Transitions
      Efficient Resource Usage
      Better Responsiveness

課前測驗

課前測驗

所需準備

我們需要一個本地網頁伺服器來測試銀行應用程式 — 不用擔心,這很簡單!如果你還沒設定好,安裝 Node.js 之後,在專案目錄執行 npx lite-server 即可。此指令會啟動本地伺服器並自動打開瀏覽器顯示你的應用程式。

準備工作

在電腦上建立一個資料夾名為 bank,裡面放一個 index.html 檔案。我們將從這個HTML 樣板開始:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bank App</title>
  </head>
  <body>
    <!-- This is where you'll work -->
  </body>
</html>

此樣板提供了什麼:

  • 建立 正確的HTML5文件結構及DOCTYPE宣告
  • 設定 字元編碼為UTF-8支援多國文字
  • 啟用 響應式設計的viewport標籤適用手機裝置
  • 設置 出現在瀏覽器分頁標題的描述性標題
  • 創建 一個乾淨的body區域讓我們構建應用程式

📁 專案結構預覽

本課結束時,你的專案將包含:

bank/
├── index.html      <!-- Main HTML with templates -->
├── app.js          <!-- Routing and navigation logic -->
└── style.css       <!-- (Optional for future lessons) -->

檔案職責分工:

  • index.html:包含所有模板並提供應用架構
  • app.js:負責路由、導覽與模板管理
  • 模板定義登入、儀表板及其他畫面UI

HTML 模板

模板解決了網頁開發中的一個基本問題。當古騰堡在1440年代發明活字印刷時他發現不必雕刻整頁而是可製作可重複使用的字元塊並根據需要組合。HTML模板遵循同樣原理 — 不用為每個畫面建立單獨HTML檔而是定義可重用的結構並按需顯示。

flowchart TD
    A["📋 範本定義"] --> B["💬 隱藏在 DOM 中"]
    B --> C["🔍 JavaScript 尋找範本"]
    C --> D["📋 複製範本內容"]
    D --> E["🔗 附加到可見 DOM"]
    E --> F["👁️ 使用者看到內容"]
    
    G["登入範本"] --> A
    H["儀表板範本"] --> A
    I["未來範本"] --> A
    
    style A fill:#e3f2fd
    style D fill:#e8f5e8
    style F fill:#fff3e0
    style B fill:#f3e5f5

想像模板是應用程式不同部份的藍圖。就像建築師繪製一次藍圖並多次使用而不必重複畫相同房間一樣我們也只創建一次模板根據需要實例化。瀏覽器會將這些模板隱藏直到JavaScript啟用它們。

如果你要建立多個網頁畫面一個解決方案是為每個畫面建立一個HTML文件但這有些不便

  • 在切換畫面時必須重新載入完整HTML速度會慢
  • 不同畫面間共享資料較困難

另一種作法是只用一個HTML檔<template> 元素定義多個 HTML模板。模板是一段可重用而瀏覽器不會直接顯示的HTML區塊必須用JavaScript在執行時實例化。

讓我們開始打造

我們要做一個有兩個主要畫面的銀行應用登入頁與儀表板。先在HTML的body標籤內加一個佔位元素 — 所有不同畫面都將在這裡出現:

<div id="app">Loading...</div>

此佔位元素說明:

  • 建立 一個ID為 "app" 的容器,所有畫面將顯示在這裡
  • 顯示 加載中的訊息直到JavaScript初始化第一個畫面
  • 提供 一個動態內容的唯一載入點
  • 方便 JavaScript用 document.getElementById() 操控

💡 專家小技巧:由於該元素內容會被替換,我們可以放置載入中消息或指示器,顯示應用程式正在載入中。

接著在HTML中加入登入頁的模板暫時只放標題和一個連結區讓我們用來導覽。

<template id="login">
  <h1>Bank App</h1>
  <section>
    <a href="/dashboard">Login</a>
  </section>
</template>

分析這個登入模板:

  • 定義 一個唯一ID為 "login" 的模板供JavaScript定位
  • 包含 顯示應用品牌的主標題
  • 語意 <section> 元素群組相關內容
  • 提供 一個連結幫助導向儀表板頁面

接著我們增加一個儀表板的HTML模板。這頁面包含不同區塊

  • 一個標題列含頁面標題和登出連結
  • 顯示銀行帳戶目前餘額
  • 一份交易記錄,以表格形式呈現
<template id="dashboard">
  <header>
    <h1>Bank App</h1>
    <a href="/login">Logout</a>
  </header>
  <section>
    Balance: 100$
  </section>
  <section>
    <h2>Transactions</h2>
    <table>
      <thead>
        <tr>
          <th>Date</th>
          <th>Object</th>
          <th>Amount</th>
        </tr>
      </thead>
      <tbody></tbody>
    </table>
  </section>
</template>

了解儀表板模板各部分:

  • 語意 <header> 元素構造頁首並含導覽連結
  • 統一顯示 應用名稱品牌
  • 包含 一個登出連結,路由回登入頁
  • 顯示 專門區塊呈現當前帳戶餘額
  • 正確結構HTML表格組織交易資料
  • 定義 表格標題列分為日期、物件及金額欄
  • 表格主體留空,待動態注入內容

💡 專家小技巧:想預覽模板實際呈現,可將 <template></template> 標籤包在 <!-- --> 註解內,即會顯示裡面內容。

🔄 教學檢視點

模板系統理解在寫JavaScript前請確定你知道

  • 模板與普通HTML元素的差異
  • 模板為何會隱藏直到JavaScript啟用
  • 模板中語意HTML結構的重要性
  • 模板如何實現UI元件重複使用

快速自我測驗:如果把 <template> 標籤移除,會怎麼樣? 答案:內容會馬上可見,失去模板功能

架構優勢:模板提供:

  • 重用性:單一定義,多次實例
  • 效能避免重複HTML解析
  • 維護性UI結構集中管理
  • 彈性:動態切換內容

為什麼我們在模板上使用 id 屬性我們能改用類別class

用JavaScript讓模板活起來

現在我們要把模板變成可用的介面。就像3D印表機以數位藍圖實體化物件JavaScript會從我們隱藏的模板創建可見且互動的元素。

這流程遵循三個一致的步驟,是現代網頁開發的基石。理解後,你會在許多框架及函式庫中看到相同模式。

若你嘗試將現有HTML載入瀏覽器會看到只顯示 Loading...因為我們尚未寫JavaScript來實例化並顯示模板。

執行模板實例化通常分3步

  1. 透過 document.getElementById 取得DOM中的模板元素。
  2. cloneNode 複製模板元素。
  3. 把複製品附加到DOM中可見的元素下例如用 appendChild
flowchart TD
    A[🔍 步驟 1尋找範本] --> B[📋 步驟 2複製範本]
    B --> C[🔗 步驟 3附加到 DOM]
    
    A1["document.getElementById('login')"] --> A
    B1["template.content.cloneNode(true)"] --> B  
    C1["app.appendChild(view)"] --> C
    
    C --> D[👁️ 範本呈現在使用者面前]
    
    style A fill:#e1f5fe
    style B fill:#f3e5f5
    style C fill:#e8f5e8
    style D fill:#fff3e0

此流程視覺解析:

  • 步驟1 定位DOM中隱藏的模板元素
  • 步驟2 製作可安全修改的可用複本
  • 步驟3 將複本插入可見的頁面區域
  • 結果 是一個用戶可互動的功能畫面

為何要先複製模板再附加進DOM如果沒這步驟會怎樣

任務

在專案資料夾新增 app.js 文件並在HTML <head> 區塊引入:

<script src="app.js" defer></script>

理解這個腳本引入:

  • 連結 JavaScript檔案至HTML文件
  • 使用 defer 屬性確保腳本在HTML解析完後執行
  • 確保 DOM元素皆已載入才執行腳本
  • 遵循 現代最佳腳本載入與效能慣例

接著,在 app.js 中創建一個新函式 updateRoute

function updateRoute(templateId) {
  const template = document.getElementById(templateId);
  const view = template.content.cloneNode(true);
  const app = document.getElementById('app');
  app.innerHTML = '';
  app.appendChild(view);
}

步驟說明:

  • 用ID定位 相應的模板元素
  • cloneNode(true) 深度複製模板內容
  • 找出 app容器元素顯示區域
  • 清空 app容器現有內容
  • 將複製內容 插入至可見DOM中

現在呼叫此函式並輸入一個模板ID看看結果。

updateRoute('login');

此函式呼叫所達成:

  • 啟用 登入模板傳入其ID作為參數
  • 展示 程式切換應用畫面的方式
  • 登入頁取代原先的「Loading...」訊息

這段程式碼 app.innerHTML = ''; 作用為何?不寫會怎樣?

建立路由Routes

路由本質是將網址(URL)對應到正確內容。想像早期電話接線員以交換臺將通話連接至正確電話號碼 — 網路路由作用類似接收URL請求並決定顯示哪些內容。

flowchart LR
    A["🌐 URL 路徑<br/>/dashboard"] --> B["🗺️ 路由物件<br/>查詢"]
    B --> C["🎯 範本 ID<br/>'dashboard'"]
    C --> D["📌 找到範本<br/>getElementById"]
    D --> E["👁️ 顯示畫面<br/>複製並附加"]
    
    F["📍 /login"] --> G["🎯 'login'"]
    H["📍 /unknown"] --> I["❌ 找不到"]
    I --> J["🔄 重新導向到 /login"]
    
    style B fill:#e3f2fd
    style E fill:#e8f5e8
    style I fill:#ffebee
    style J fill:#fff3e0

傳統網頁伺服器根據不同URL回傳不同HTML文件。因為我們做的是單頁應用程式必須用JavaScript自己處理路由這讓我們能更靈活控管用戶體驗與效能。

flowchart LR
    A["🌐 URL 路徑<br/>/dashboard"] --> B["🗺️ 路由物件<br/>查找"]
    B --> C["🎯 範本 ID<br/>'dashboard'"]
    C --> D["📄 找範本<br/>getElementById"]
    D --> E["👁️ 顯示畫面<br/>複製並附加"]
    
    F["📍 /login"] --> G["🎯 'login'"]
    H["📍 /unknown"] --> I["❌ 找不到"]
    I --> J["🔄 重新導向到 /login"]
    
    style B fill:#e3f2fd
    style E fill:#e8f5e8
    style I fill:#ffebee
    style J fill:#fff3e0

了解路由流程:

  • URL變更 觸發路由對照查詢
  • 有效路由 對應特定模板ID以渲染畫面
  • 無效路由 觸發預設行為以避免顯示錯誤狀態
  • 模板渲染 跟先前學的三步驟處理一致

提到網頁應用,我們稱「路由」是映射 URLs 到應該顯示的特定畫面。在有多個HTML文件的網站中這會根據檔案路徑自動完成。例如專案中有以下檔案

mywebsite/index.html
mywebsite/login.html
mywebsite/admin/index.html

若你用 mywebsite 當作根目錄設置網頁伺服器URL會對應為

https://site.com            --> mywebsite/index.html
https://site.com/login.html --> mywebsite/login.html
https://site.com/admin/     --> mywebsite/admin/index.html

但我們的網頁應用只有一個HTML檔包含全部畫面因此這種預設行為不適用。我們必須自己建立對照表並用JavaScript更新顯示的模板。

任務

我們將使用一個簡單物件實作 映射 將URL路徑對應至模板。把這個物件加在 app.js 頂端。

const routes = {
  '/login': { templateId: 'login' },
  '/dashboard': { templateId: 'dashboard' },
};

理解此路由設定:

  • 定義 URL路徑與模板識別碼的對應映射
  • 物件語法關鍵字是URL路徑值包含模板資訊
  • 方便 查找對應URL該顯示哪個模板
  • 建立 擴展性良好的架構以便未來新增路由 現在讓我們稍微修改一下 updateRoute 函式。我們不直接將 templateId 作為參數傳入,而是先從當前 URL 中擷取,然後透過之前建立的對應表取得相應的模板 ID 值。我們可以使用 window.location.pathname 來取得 URL 中的路徑部分。
function updateRoute() {
  const path = window.location.pathname;
  const route = routes[path];

  const template = document.getElementById(route.templateId);
  const view = template.content.cloneNode(true);
  const app = document.getElementById('app');
  app.innerHTML = '';
  app.appendChild(view);
}

拆解這裡發生的事情:

  • 擷取 瀏覽器 URL 中的目前路徑,使用 window.location.pathname
  • 查詢 routes 物件中相對應的路由設定
  • 取出 路由設定中的模板 ID
  • 沿用 之前的模板渲染流程
  • 建立 一個根據 URL 變更動態回應的系統

這裡我們將宣告的路由映射到對應的模板。你可以透過手動變更瀏覽器的 URL 來測試它是否正確運作。

如果你輸入一個未知的路徑會發生什麼?我們該怎麼解決?

新增導航

當路由機制建置完成後,用戶需要一種方法在應用程式中導航。傳統網站點擊連結會重新載入整個頁面,而我們想要在不重新整理頁面的情況下更新 URL 和內容。這會創造出更流暢的體驗,類似桌面應用程式在不同檢視間切換的感覺。

我們需要協調兩件事:更新瀏覽器的 URL讓使用者可以書籤及分享連結以及顯示相對應的內容。正確實作下這將建構出使用者對現代應用程式所期望的無縫導航體驗。

sequenceDiagram
    participant User
    participant Browser
    participant App
    participant Template
    
    User->>Browser: 點擊「登入」連結
    Browser->>App: onclick 事件觸發
    App->>App: preventDefault() 並導向('/dashboard')
    App->>Browser: history.pushState('/dashboard')
    Browser->>Browser: URL 更新為 /dashboard
    App->>App: 呼叫 updateRoute()
    App->>Template: 找到並複製儀表板模板
    Template->>App: 回傳複製內容
    App->>Browser: 用模板替換應用內容
    Browser->>User: 顯示儀表板畫面
    
    Note over User,Template: 使用者點擊瀏覽器返回按鈕
    
    User->>Browser: 點擊返回按鈕
    Browser->>Browser: 歷史記錄回到 /login
    Browser->>App: popstate 事件觸發
    App->>App: 自動呼叫 updateRoute()
    App->>Template: 找到並複製登入模板
    Template->>App: 回傳複製內容
    App->>Browser: 用模板替換應用內容
    Browser->>User: 顯示登入畫面

🔄 教學核對點

單頁應用程式架構:檢視你對整體系統的理解:

  • 客戶端路由與傳統伺服器端路由有何不同?
  • 為什麼 History API 對 SPA 的導航至關重要?
  • 模板如何在不重新整理的情況下實現動態內容?
  • 事件處理在攔截導航上扮演什麼角色?

系統整合:你的 SPA 展現了:

  • 模板管理:可重複使用的 UI 元件與動態內容
  • 客戶端路由:不透過伺服器請求管理 URL
  • 事件驅動架構:響應式導航與使用者互動
  • 瀏覽器整合:正確支援歷史紀錄及前進後退鍵
  • 效能優化:快速轉場與降低伺服器負載

專業模式:你已實作:

  • 模型-視圖分離:模板與應用邏輯分開
  • 狀態管理URL 狀態與顯示內容同步
  • 漸進式增強JavaScript 強化基本 HTML 功能
  • 使用者體驗:流暢且類 App 的無刷新導航

<EFBFBD> 架構洞察:導航系統元件

你正在建構:

  • 🔄 URL 管理:更新瀏覽器位址欄且不重新整理頁面
  • 📋 模板系統:根據當前路由動態切換內容
  • 📚 歷史整合:維持瀏覽器前進/後退按鈕功能
  • 🛡️ 錯誤處理:對無效或缺失路由提供優雅備援

元件如何協作:

  • 監聽 導航事件(點擊、歷史變動)
  • 更新 使用 History API 設定 URL
  • 渲染 對應路由的模板
  • 保持 用戶體驗的連續性

我們應用的下一步是加入在頁面間導航的功能,不需手動更改 URL。這包含兩件事

  1. 更新當前 URL
  2. 根據新 URL 更新顯示模板

第二部分我們已用 updateRoute 函式解決,現在要處理如何更新當前 URL。

我們得使用 JavaScript特別是 history.pushState,它允許更新 URL 並在瀏覽歷史中新增紀錄,但不會重新載入 HTML。

⚠️ 重要提示:雖然 HTML 錨點元素 <a href> 可用於不同 URL 的超鏈結,但預設會導致瀏覽器重新載入。使用自訂 JavaScript 控制路由時,需要在點擊事件中透過 preventDefault() 防止此行為。

任務

讓我們建立一個可以用來在應用程式中導航的新函式:

function navigate(path) {
  window.history.pushState({}, path, path);
  updateRoute();
}

理解這個導航函式:

  • 使用 history.pushState 更新瀏覽器 URL 到新路徑
  • 新增 瀏覽器歷史紀錄堆疊的紀錄,以支援前進/後退按鈕
  • 觸發 updateRoute() 函式,顯示相對應模板
  • 維持 單頁應用無重新整理的使用體驗

此方法先根據指定路徑更新目前 URL再更新模板。window.location.origin 屬性會回傳 URL 根部,可用來從路徑重建完整 URL。

現在我們擁有此函式後,針對找不到匹配路由的情況,我們會在 updateRoute 函式裡加入回退方案,轉向現有路由中的其中一頁。

function updateRoute() {
  const path = window.location.pathname;
  const route = routes[path];

  if (!route) {
    return navigate('/login');
  }

  const template = document.getElementById(route.templateId);
  const view = template.content.cloneNode(true);
  const app = document.getElementById('app');
  app.innerHTML = '';
  app.appendChild(view);
}

記住這些重點:

  • 檢查 當前路徑是否存在路由
  • 無效路由時 重新導向至登入頁
  • 提供 備援機制避免導致導航破裂
  • 確保 使用者即使輸入錯誤 URL 也看得到有效頁面

若找不到路由,我們會重定向至 login 頁面。

接著建立一個函式,在點擊連結時取得該 URL 並阻止瀏覽器預設行為:

function onLinkClick(event) {
  event.preventDefault();
  navigate(event.target.href);
}

拆解此點擊處理器:

  • 透過 preventDefault() 防止瀏覽器預設的連結行為
  • 擷取 被點擊連結元素的目標 URL
  • 呼叫 我們的自訂導航函式取代重新載入頁面
  • 保持 順暢的單頁應用體驗
<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>

此 onclick 綁定達成:

  • 每個連結接入我們的自訂導航系統
  • 點擊事件傳給 onLinkClick 函式處理
  • 實現 無刷新頁面的流暢導航
  • 維持 使用者能書籤或分享的正確 URL 結構

onclick 屬性綁定了 click 事件的 JavaScript 代碼,這裡是呼叫 navigate() 函式。

試試點擊這些連結,你應能在不同畫面間成功切換。

history.pushState 方法是 HTML5 標準的一部分,且所有現代瀏覽器均有實作。如需支援舊版瀏覽器,有個技巧可用:利用路徑前的 hash (#) 實作路由,這樣可以使用傳統錨點導航且不會重新載入頁面,因為 hash 主要用於頁面內部連結。

支援前進與後退按鈕

前進與後退按鈕是網頁瀏覽的根本,就像太空任務中的 NASA 控制員可以檢視先前系統狀態一般。使用者期望這些按鈕能正常工作,若不行就會破壞瀏覽體驗。

我們的單頁應用需要額外設定才支援此功能。瀏覽器會維護歷史堆疊(我們透過 history.pushState 持續新增),但使用者在歷史中移動時,我們的應用必須回應並更新顯示內容。

sequenceDiagram
    participant User
    participant Browser
    participant App
    participant Template
    
    User->>Browser: 點擊「登入」連結
    Browser->>App: onclick 事件觸發
    App->>App: preventDefault() 並導航至 '/dashboard'
    App->>Browser: history.pushState('/dashboard')
    Browser->>Browser: URL 更新至 /dashboard
    App->>App: 呼叫 updateRoute()
    App->>Template: 找到並複製 dashboard 模板
    Template->>App: 回傳複製的內容
    App->>Browser: 以模板取代應用內容
    Browser->>User: 顯示 dashboard 畫面
    
    Note over User,Template: 使用者點擊瀏覽器返回鍵
    
    User->>Browser: 點擊返回鍵
    Browser->>Browser: 歷史紀錄退回到 /login
    Browser->>App: popstate 事件觸發
    App->>App: 自動呼叫 updateRoute()
    App->>Template: 找到並複製登入模板
    Template->>App: 回傳複製的內容
    App->>Browser: 以模板取代應用內容
    Browser->>User: 顯示登入畫面

重要互動點:

  • 使用者行動:點擊或瀏覽器按鈕觸發導航
  • 應用攔截:連結點擊事件防止頁面刷新
  • 歷史 API:管理 URL 變化及歷史堆疊
  • 模板:為每個畫面提供內容架構
  • 事件監聽:確保任何導航類型均有反應

使用 history.pushState 會在瀏覽器導覽歷史新增紀錄。你可以長按瀏覽器的 後退鍵 查看,應該會顯示類似以下內容:

Screenshot of navigation history

若嘗試點擊後退鍵幾次,你會看到 URL 變更且歷史紀錄更新,但畫面模板不變。

這是因為應用無法偵測每次歷史堆疊變動時應呼叫 updateRoute()。查看 history.pushState 文件 可知,當狀態發生改變(即網址轉換)時,會觸發 popstate 事件。我們會利用這點來修正問題。

任務

為確保瀏覽器歷史發生變動時模板同步更新,我們將新增函式呼叫 updateRoute(),並放在 app.js 檔案底部:

window.onpopstate = () => updateRoute();
updateRoute();

理解此歷史整合:

  • 監聽 使用者用瀏覽器前後鈕時觸發的 popstate 事件
  • 使用 箭頭函式簡潔宣告事件處理器
  • 自動 呼叫 updateRoute() 更新模板內容
  • 初始化 頁面載入時先呼叫 updateRoute() 顯示初始畫面
  • 確保 無論如何導航均顯示正確模板

💡 專家小技巧:此處使用 箭頭函式 宣告 popstate 事件處理器,簡潔明了;若改用傳統函式同樣有效。

這裡有一段箭頭函式教學影片複習:

Arrow Functions

🎥 點擊上方圖片觀看箭頭函式說明影片。

現在試著使用瀏覽器的前進與後退按鈕,確認這次顯示的路由是否隨之正確更新。

你可以在接下來 5 分鐘完成的事項

  • 測試你的銀行應用在瀏覽器前後按鈕下的導航功能
  • 嘗試在位址欄手動輸入不同 URL 測試路由機制
  • 開啟瀏覽器開發工具,檢查模板如何被克隆並插入 DOM
  • 動手加入 console.log 追蹤路由流程

🎯 你可以在這一小時內達成的目標

  • 完成課後測驗,了解 SPA 架構概念
  • 為銀行應用模板加入 CSS 美化
  • 實作 404 錯誤頁面挑戰並完善錯誤處理
  • 建立製作頁面挑戰並新增路由功能
  • 在模板切換間新增載入狀態與過場動畫

📅 你的週度 SPA 開發歷程

  • 完成完整銀行應用,涵蓋表單、資料管理與持久化
  • 增加進階路由功能,如參數路由與巢狀路由
  • 實作導航守衛與基於認證的路由控制
  • 建立可重用模板元件與元件庫
  • 新增動畫及過場提升使用者體驗流暢度
  • 將 SPA 部署到主機平台並正確設定路由配置

🌟 你一個月內的前端架構大師養成

  • 使用 React、Vue 或 Angular 建置複雜 SPA
  • 學習進階狀態管理模式與函式庫
  • 精通建置工具及 SPA 開發工作流程
  • 實作漸進式網頁應用 (PWA) 與離線功能
  • 研究大型 SPA 的效能優化技術
  • 貢獻開源 SPA 專案並分享知識

🎯 你的單頁應用掌握時程

timeline
    title SPA 開發與現代網頁架構學習進度
    
    section 基礎 (20 分鐘)
        模板系統: HTML 範本元素
                 : DOM 操作
                 : 內容複製
                 : 動態渲染
        
    section 路由基礎 (30 分鐘)
        用戶端導覽: URL 管理
                   : History API
                   : 路由映射
                   : 事件處理
        
    section 用戶體驗 (40 分鐘)
        導覽精進: 瀏覽器整合
                 : 返回按鈕支援
                 : 錯誤處理
                 : 流暢轉場
        
    section 架構模式 (50 分鐘)
        專業 SPA: 元件系統
                  : 狀態管理
                  : 效能優化
                  : 錯誤邊界
        
    section 進階技術 (1 週)
        框架整合: React Router
                 : Vue Router
                 : Angular Router
                 : 狀態庫
        
    section 生產技能 (1 個月)
        企業開發: 建置系統
                 : 測試策略
                 : 部署流程
                 : 效能監控

🛠️ 你的 SPA 開發工具總覽

完成本課後,你已精通:

  • 模板架構:可重複使用的 HTML 元件與動態內容渲染
  • 客戶端路由:無刷新頁面切換的 URL 管理與導航
  • 瀏覽器整合History API 使用及前進/後退支援
  • 事件驅動系統:導航處理與使用者互動管理
  • DOM 操作:模板克隆、內容切換與元素管理
  • 錯誤處理:對無效路由及缺失內容的優雅處理
  • 效能模式:高效內容載入與渲染策略

實務應用:你的 SPA 技能可直接應用於:

  • 現代網頁應用React、Vue、Angular 等框架開發
  • 漸進式網頁應用:具備離線能力與類 App 體驗
  • 企業儀表板:多視圖複雜商業應用
  • 電商平台:產品目錄、購物車及結帳流程
  • 內容管理:動態內容建立與編輯介面
  • 行動開發:使用網路技術的混合應用程式

所獲專業技能:你現在能夠:

  • 架構 單頁應用程式並維持適當的關注點分離
  • 實作 隨應用複雜度可擴充的客戶端路由系統
  • 除錯 複雜的導覽流程,利用瀏覽器開發者工具
  • 優化 透過有效的模板管理提升應用程式效能
  • 設計 原生且具回應性的使用者體驗

掌握的前端開發概念

  • 元件架構:可重複使用的 UI 範式和模板系統
  • 狀態同步:網址狀態管理與瀏覽器歷史紀錄
  • 事件驅動程式設計:使用者互動處理與導覽
  • 效能優化:高效的 DOM 操控與內容載入
  • 使用者體驗設計:流暢過場與直覺性導覽

下一步:你已準備好探索現代前端框架、進階狀態管理,或打造複雜的企業級應用程式!

🌟 成就解鎖:你已建立具有現代網路架構模式的專業單頁應用基礎!


GitHub Copilot Agent 挑戰 🚀

使用 Agent 模式完成以下挑戰:

說明: 強化銀行應用程式,實作錯誤處理及針對無效路徑的 404 頁面模板,改善使用者瀏覽不存在頁面時的體驗。

提示: 建立一個新的 HTML 模板id 為 "not-found",以顯示具友善提示的 404 錯誤頁面並包含樣式。接著修改 JavaScript 路由邏輯,在使用者瀏覽無效網址時顯示此模板,並新增一個「回首頁」按鈕,可導回登入頁面。

更多關於agent mode的資訊。

🚀 挑戰

為此應用程式新增第三頁的模板與路由,該頁展示製作人員名單。

挑戰目標:

  • 建立 一個新的 HTML 模板並具合適內容結構
  • 加入 新路由至路由配置物件
  • 包含 導覽連結以往返製作人員頁面
  • 測試 確認所有導覽功能正常並符合瀏覽器歷史紀錄運作

課後小測驗

課後小測驗

複習與自學

路由是 Web 開發中意外地棘手部分,尤其當 Web 從頁面重新整理行為轉向單頁應用程式的頁面刷新時。閱讀一點有關 Azure 靜態網站服務 如何處理路由。你能解釋該文件中描述的某些決策為什麼是必要的嗎?

額外學習資源:

  • 探索 React Router 和 Vue Router 等熱門框架如何實作客戶端路由
  • 研究 基於 hash 的路由與 history API 路由的差異
  • 了解 伺服器端渲染SSR及其對路由策略的影響
  • 調查 漸進式網路應用程式PWA如何處理路由與導覽

作業

改善路由


免責聲明
本文件係使用 AI 翻譯服務 Co-op Translator 進行翻譯。我們雖致力於提供準確的翻譯,但請注意,機器翻譯可能存在錯誤或不準確之處。原始語言版本的文件應視為權威來源。對於重要資訊,建議委託專業人工翻譯。我們不對因使用本翻譯而產生的任何誤解或錯誤詮釋負責。