# LESSON-19｜Vue 3 CDN：createApp、setup、mount

> 對象：完全沒有前端概念的入門者
>
> 時間：3 小時
>
> **本堂專屬焦點：**用 Vue 3 CDN 建立 createApp、setup 與 mount 的最小流程

## 1. 課程目標

不使用 Vite，完成一個可由 CDN 載入、由 setup 提供資料並掛載到 #app 的 Vue 3 靜態最小應用。

## 2. 任務情境

網站先需要一個可由瀏覽器直接開啟的 Vue 入口；本堂暫時只把靜態服務介紹交給 Vue 渲染，不先處理互動狀態。

## 3. 先備知識與檔案結構

本堂不要求先會 Vue、npm、Vite 或 JavaScript 框架。只要知道如何用編輯器儲存 HTML／JavaScript／CSS、用瀏覽器開啟 examples/minimal.html、按右鍵開啟 DevTools，並在 Elements、Console、Network 讀取證據。先完成瀏覽器、HTML、script 與 CDN 的橋接，再開始 Starter。

### 檔案地圖

- `examples/minimal.html`：只讀最小實驗：完整示範 CDN → createApp → setup → return → mount 的靜態流程。
- `starter/files/index.html`：Starter HTML：故意缺少 Vue CDN 與 Vue template，讓學生依序補上。
- `starter/files/main.js`：Starter JavaScript：保留 createApp 與 mount，等待學生補上 setup 與 return。
- `checkpoint/files/main.js`：Checkpoint JavaScript：CDN、createApp、setup 與 return 完整，只留下 mount 缺口。
- `solution/files/index.html`：Solution HTML：唯一 #app、完整 Vue template 與位於容器外的兩個 script。
- `solution/files/main.js`：Solution JavaScript：只有一個 createApp、setup、return 與 mount。

## 授課補強｜180 分鐘教學節奏

**本堂專屬焦點：**用 Vue 3 CDN 建立 createApp、setup 與 mount 的最小流程

固定的是八段時間，變化的是本堂檔案、教師操作、學生產出與驗收證據。

| 時間 | 教學活動 | 教師交付 | 學生產出 |
| --- | --- | --- | --- |
| 0–10 分鐘 | 情境導入｜網站先需要一個可由瀏覽器直接開啟的 Vue 入口；本堂暫時只把靜態服務介紹交給 Vue 渲染，不先處理互動狀態。 | 展示 index.html、Vue CDN script、#app、createApp、setup、mount 目前的狀態，先請學生預測「不使用 Vite，完成一個可由 CDN 載入、由 setup 提供資料並掛載到 #app 的 Vue 3 靜態最小應用。」完成後會出現什麼畫面或資料結果。 | 說出本堂問題與完成目標。；完成後：知道要從 index.html、Vue CDN script、#app、createApp、setup、mount 找到第一個可觀察結果。；驗收：以Network CDN 200、typeof Vue 為 object、唯一 #app、setup 回傳值正確渲染且 Console 無 Vue 執行錯誤中的第一項作為導入前後的對照證據。 |
| 10–35 分鐘 | 概念建立｜CDN、createApp、setup、mount 與 Vue 應用邊界 | 用 index.html、Vue CDN script、#app、createApp、setup、mount 中的最小片段逐詞解釋 CDN、createApp、setup、mount 與 Vue 應用邊界，每介紹一個詞就回到瀏覽器或 DevTools 指出可觀察結果。 | 完成名詞對照表，並先回答一題預測題。；完成後：能用自己的話解釋 CDN、createApp、setup、mount 與 Vue 應用邊界。；驗收：口頭回答一題預測題，並指出Network CDN 200、typeof Vue 為 object、唯一 #app、setup 回傳值正確渲染且 Console 無 Vue 執行錯誤中對應的畫面、Console、Network、DOM 或資料證據。 |
| 35–55 分鐘 | 教師示範｜在 index.html 載入 Vue 3 CDN，建立 app 物件並 mount 到 #app，讓 setup 回傳的服務標題與說明出現在畫面。 | 從最小可執行範例開始，逐次修改 index.html、Vue CDN script、#app、createApp、setup、mount；每次只改一個檢查點，先預測再重新整理或操作。 | 跟著完成一次修改，記下修改前後差異。；完成後：看到 Network CDN 200、typeof Vue 為 object、唯一 #app、setup 回傳值正確渲染且 Console 無 Vue 執行錯誤 中至少一項可觀察結果。；驗收：保留一次修改前後畫面，並記下Network CDN 200、typeof Vue 為 object、唯一 #app、setup 回傳值正確渲染且 Console 無 Vue 執行錯誤中至少兩項觀察結果。 |
| 55–95 分鐘 | 學生跟做｜不使用 Vite，完成一個可由 CDN 載入、由 setup 提供資料並掛載到 #app 的 Vue 3 靜態最小應用。 | 將示範拆成 10–15 分鐘一個小檢查點，巡迴確認學生真的修改到 index.html、Vue CDN script、#app、createApp、setup、mount，卡住時先要求說出症狀與證據。 | 在自己的專案完成：不使用 Vite，完成一個可由 CDN 載入、由 setup 提供資料並掛載到 #app 的 Vue 3 靜態最小應用。；完成後：核心成果能在自己的專案重現，而不是只在講師畫面成功。；驗收：提交核心成果、修改檔案清單，以及Network CDN 200、typeof Vue 為 object、唯一 #app、setup 回傳值正確渲染且 Console 無 Vue 執行錯誤中可重現的至少兩項證據。 |
| 95–110 分鐘 | 觀察與除錯｜故意將 CDN 放在 main.js 後面或 mount 到不存在的 #app，從 Network、typeof Vue 與 Console 找原因。 | 故意重現「故意將 CDN 放在 main.js 後面或 mount 到不存在的 #app，從 Network、typeof Vue 與 Console 找原因。」，示範從症狀、證據、假設、單一修正到重新驗證的除錯紀錄。 | 重現一個錯誤，再只修改一處並重新驗證。；完成後：能寫出症狀、原因、修正與修正後結果。；驗收：留下錯誤狀態與修正後狀態的對照，證明Network CDN 200、typeof Vue 為 object、唯一 #app、setup 回傳值正確渲染且 Console 無 Vue 執行錯誤中的錯誤已消失。 |
| 110–155 分鐘 | 情境變體與獨立挑戰｜將靜態服務介紹換成另一個服務型商家的品牌、標題與說明，保留同一個 CDN → createApp → setup → mount 順序。 | 先圈出 index.html、Vue CDN script、#app、createApp、setup、mount 中不變的技術結構，再示範如何完成「將靜態服務介紹換成另一個服務型商家的品牌、標題與說明，保留同一個 CDN → createApp → setup → mount 順序。」，最後請學生獨立完成同一變體。 | 完成變體：將靜態服務介紹換成另一個服務型商家的品牌、標題與說明，保留同一個 CDN → createApp → setup → mount 順序。；完成後：能說明哪些結構保留、哪些內容替換，且沒有引入超出本堂範圍的技術。；驗收：將變體結果與原始結果並列，附上檔案或操作位置與一次重新驗證紀錄。 |
| 155–175 分鐘 | 驗收、展示與討論｜Network CDN 200、typeof Vue 為 object、唯一 #app、setup 回傳值正確渲染且 Console 無 Vue 執行錯誤 | 依 Network CDN 200、typeof Vue 為 object、唯一 #app、setup 回傳值正確渲染且 Console 無 Vue 執行錯誤 逐項抽查學生的畫面、Console、Network、DOM 或資料與檔案，請學生先展示證據，再討論不同解法。 | 展示：Network CDN 200、typeof Vue 為 object、唯一 #app、setup 回傳值正確渲染且 Console 無 Vue 執行錯誤；完成後：能回答「如果驗收失敗，下一個要查什麼？」。；驗收：留下可重現的驗收包：結果截圖或網址、檔案位置、檢查步驟與實際觀察。 |
| 175–180 分鐘 | 重點回顧與下堂銜接｜響應式渲染：下一堂才會使用 ref、computed、v-for 與 v-if 管理會改變的服務清單。 | 用「概念、操作、證據」三問回看 index.html、Vue CDN script、#app、createApp、setup、mount 的成果，再說明它如何接到「響應式渲染：下一堂才會使用 ref、computed、v-for 與 v-if 管理會改變的服務清單。」。 | 寫下三句回顧：我理解了什麼、我做出了什麼、我用什麼證據確認；再預測下一堂會修改哪個檔案。；完成後：能用一句話說明本堂成果如何銜接：響應式渲染：下一堂才會使用 ref、computed、v-for 與 v-if 管理會改變的服務清單。；驗收：講師抽問一位學生重述響應式渲染：下一堂才會使用 ref、computed、v-for 與 v-if 管理會改變的服務清單。，並收回一項本堂驗收證據。 |

## 4. 觀念拆解

本堂第一次出現的詞，先從「白話 → 正式定義 → 何時使用 → 最小例子 → 可觀察證據 → 混淆概念」建立完整理解。

### 瀏覽器（browser）

- **白話：**把 HTML、CSS 與 JavaScript 讀成可以看的網頁，並執行 Vue。
- **正式定義：**解析文件、載入資源、建立 DOM，並在目前頁面執行 JavaScript 的用戶端軟體。
- **使用時機：**要開啟教材、觀察畫面或用 DevTools 找錯誤時。
- **最小範例：**用瀏覽器開啟 `examples/minimal.html`。
- **觀察證據：**畫面、Elements、Console 與 Network 都是瀏覽器執行後的證據。
- **容易混淆：**和編輯器混淆；編輯器修改檔案，瀏覽器呈現與執行檔案。

### HTML（HyperText Markup Language）

- **白話：**描述頁面內容與結構的文字語言。
- **正式定義：**以元素與屬性描述文件結構，讓瀏覽器建立 DOM。
- **使用時機：**要放置 `main`、`h1`、`p` 或 Vue 的 `#app` 容器時。
- **最小範例：**`<main id="app"><h1>{{ title }}</h1></main>`。
- **觀察證據：**Elements 能看到唯一的 `#app` 與其子元素。
- **容易混淆：**和 CSS 混淆；HTML 說明內容結構，CSS 說明外觀。

### script（script element）

- **白話：**告訴瀏覽器要載入或執行 JavaScript 的 HTML 標籤。
- **正式定義：**HTML 用來嵌入或引用可執行腳本資源的元素。
- **使用時機：**要載入 Vue CDN 或自己的 `main.js` 時。
- **最小範例：**`<script src="main.js" defer></script>`。
- **觀察證據：**Network 能看到請求，Console 能看到腳本執行結果。
- **容易混淆：**和 `link` 混淆；script 載入行為，link 通常載入 CSS。

### CDN（Content Delivery Network）

- **白話：**從網路提供可以直接使用的 Vue 程式。
- **正式定義：**由分散式伺服器提供靜態資源的發布方式；本堂以 script 載入 Vue global build。
- **使用時機：**不使用 Vite、npm 或 import，仍要在 HTML 使用 Vue 3 時。
- **最小範例：**`<script src="${lesson21VueCdn}"></script>`。
- **觀察證據：**Network 的 Vue 請求狀態為 200，Console 執行 `typeof Vue` 得到 `object`。
- **容易混淆：**和 npm 套件安裝混淆；CDN 是瀏覽器載入，不是本機建置工具。

### Vue global build（Vue global build）

- **白話：**透過 script 載入後，可以直接使用全域 `Vue` 物件的版本。
- **正式定義：**將 Vue API 暴露在 `window.Vue` 上、可不使用 ES module import 的發布版本。
- **使用時機：**本堂使用 CDN、直接開啟 HTML，且還沒有 Vite 專案時。
- **最小範例：**`const VueApi = window.Vue;`。
- **觀察證據：**Console 的 `typeof Vue` 為 `object`，main.js 能呼叫 `VueApi.createApp`。
- **容易混淆：**和 module build 混淆；global build 不需要 `import`。

### window（Window object）

- **白話：**目前瀏覽器分頁提供給 JavaScript 的全域物件。
- **正式定義：**代表瀏覽器視窗或分頁執行環境的全域物件；CDN global build 會把 `Vue` 放在它上面。
- **使用時機：**需要確認外部 script 載入後提供了哪個全域名稱時。
- **最小範例：**`window.Vue === Vue`。
- **觀察證據：**Console 讀取 `window.Vue` 不為 `undefined`。
- **容易混淆：**和 DOM 的 `document` 混淆；window 是執行環境，document 是目前頁面。

### createApp（createApp）

- **白話：**建立一個 Vue 應用程式的起點。
- **正式定義：**從根元件選項建立 Vue application instance 的函式。
- **使用時機：**要讓一個 HTML 區域由 Vue 接手管理時。
- **最小範例：**`const app = VueApi.createApp({ setup() { return {}; } });`。
- **觀察證據：**app 建立後仍未顯示；要等 mount 才接手 `#app`。
- **容易混淆：**和 mount 混淆；createApp 建立應用，mount 指定容器。

### setup（setup function）

- **白話：**集中放置這個 Vue 應用要提供給畫面的資料與函式。
- **正式定義：**Composition API 的初始化函式；其回傳值可以在根 template 中使用。
- **使用時機：**要先提供靜態標題、說明或之後會使用的狀態時。
- **最小範例：**`setup() { const title = "安心維護服務"; return { title }; }`。
- **觀察證據：**template 使用的名稱和 setup return 欄位一致。
- **容易混淆：**和 createApp 混淆；createApp 建立 app，setup 定義 app 要使用的資料。

### return（return statement）

- **白話：**把函式內準備好的結果交出去。
- **正式定義：**結束函式執行並把值交回呼叫端；Vue setup 的回傳物件會暴露給 template。
- **使用時機：**setup 裡宣告資料，但 template 需要讀取它時。
- **最小範例：**`return { title, description };`。
- **觀察證據：**沒有 return 時，template 可能找不到預期名稱；有 return 時畫面出現實際文字。
- **容易混淆：**和宣告混淆；const 只是建立資料，return 才把資料交給外部。

### template（Vue template）

- **白話：**描述畫面要顯示哪些 HTML 與資料的樣板。
- **正式定義：**Vue 解析並轉換成 DOM 的模板內容；本堂使用直接寫在 `#app` 裡的 DOM template。
- **使用時機：**要把 setup 回傳的資料放進 HTML 畫面時。
- **最小範例：**`<h1>{{ title }}</h1>`。
- **觀察證據：**Elements 的大括號不再原樣顯示，而是實際的 title 文字。
- **容易混淆：**和完整 HTML 文件混淆；template 是 Vue 接手範圍內的畫面描述。

### 插值（interpolation）

- **白話：**用兩個大括號把資料放到畫面文字裡。
- **正式定義：**Vue template 使用 `{{ expression }}` 將可讀取的資料值渲染成文字。
- **使用時機：**標題、說明或狀態文字要來自 setup 資料時。
- **最小範例：**`<p>{{ description }}</p>`。
- **觀察證據：**畫面顯示 description 的值，而不是 `{{ description }}` 字串。
- **容易混淆：**和 JavaScript template literal 混淆；插值是 Vue template 的語法。

### DOM（Document Object Model）

- **白話：**瀏覽器把 HTML 解析成 JavaScript 可以觀察的文件樹。
- **正式定義：**代表目前文件節點、階層、屬性與文字狀態的程式介面。
- **使用時機：**要確認 Vue 實際接手了哪個元素，或畫面文字是否真的改變時。
- **最小範例：**在 Elements 選取 `#app`，查看它的子元素。
- **觀察證據：**Elements 中的 DOM 與畫面實際文字一致。
- **容易混淆：**和編輯器裡的原始 HTML 混淆；DOM 是瀏覽器目前執行後的結果。

### mount（mount）

- **白話：**把 Vue 應用接到頁面指定的元素，開始渲染。
- **正式定義：**將 application instance 掛載到 DOM container 並啟動渲染的操作。
- **使用時機：**createApp 與 setup 完成、準備讓 Vue 顯示在畫面上時。
- **最小範例：**`app.mount("#app");`。
- **觀察證據：**`#app` 裡的大括號變成實際文字；沒有 mount 時會保留原始 template。
- **容易混淆：**和 DOM append 混淆；mount 啟動 Vue 管理，append 只加入 DOM 節點。

### application instance（application instance）

- **白話：**createApp 建立出來、之後要 mount 的 Vue 應用物件。
- **正式定義：**由 `createApp` 回傳、可設定並掛載到一個 DOM container 的應用實例。
- **使用時機：**要說明 `const app` 為什麼不是普通資料，而是接下來要 mount 的對象時。
- **最小範例：**`const app = VueApi.createApp({ ... }); app.mount("#app");`。
- **觀察證據：**同一個 app 只有一次 mount，且 mount 的 selector 對應 HTML 的 id。
- **容易混淆：**和 `#app` 混淆；app 是 JavaScript 應用，#app 是 HTML 容器。

## 5. Live Lab

### 最小可執行實驗

- **入口：**`examples/minimal.html`
- **操作：**直接開啟 examples/minimal.html；先在 Network 找到 Vue CDN，再在 Elements 選取唯一的 #app，最後用 Console 執行 typeof Vue。
- **預期結果：**畫面顯示實際 title、description 與完成訊息；Network 的 Vue CDN 成功，Console 的 typeof Vue 為 object，#app 內不保留大括號。
- **重設方式：**重新整理 examples/minimal.html；不要把這份最小實驗改成期末專案。
- **第一個檢查位置：**先確認開啟的是 examples/minimal.html，再依序檢查 Network 的 Vue CDN、Console 的 typeof Vue 與 Elements 的唯一 #app。

### Step 1：先分清楚瀏覽器、CDN 與 Vue global build

- **教學目的：**讓學生知道 HTML 是入口、CDN script 提供 Vue，而 main.js 要等 Vue 存在後才能呼叫 createApp。
- **講師白話解釋：**先請學生說出預測，再說明這一步只處理一個責任。
- **精確檔案與區塊：**examples/minimal.html 的兩個 script 與 Console／Network
- **修改前：**先開啟最小實驗，記下畫面、Network 的 Vue CDN 狀態，以及 Console 的 typeof Vue；development build 提示不是本堂錯誤。
- **本次只修改：**只確認 Vue CDN 在自己的 script 前面、檔案成功載入，這一步不先加入 ref、computed 或事件。
- **程式碼或操作：**

  ```text
  <script src="https://unpkg.com/vue@3.5.40/dist/vue.global.js"></script>
  <script src="main.js" defer></script>
  
  // DevTools Console
  typeof Vue
  ```
- **預期結果：**Network 的 Vue CDN 與 main.js 成功，Console 的 typeof Vue 是 object，畫面仍由唯一的 #app 負責。
- **學生可能的錯誤答案：**看到 development build 提示就當成錯誤，或先改元件與互動而沒有確認 CDN 是否成功。
- **講師追問：**如果 Console 顯示 Vue is not defined，你第一個要查 Network、setup，還是按鈕事件？為什麼？
- **DevTools／Console／Network／DOM 驗收：**Network URL／狀態碼、Console 第一個錯誤與 typeof Vue 結果。
- **卡住時的單一檢查：**只確認目前開啟的入口與 Vue CDN script 順序，不同時修改其他檔案。

### Step 2：把 Vue CDN 放進入口 HTML

- **教學目的：**先讓瀏覽器取得 Vue，再讓後面的 main.js 有可以使用的全域 API。
- **講師白話解釋：**先請學生說出預測，再說明這一步只處理一個責任。
- **精確檔案與區塊：**starter/files/index.html 的 body 結尾 script 區塊
- **修改前：**Starter 故意只有自己的 main.js，開啟時 Console 會出現 VueApi 相關錯誤。
- **本次只修改：**在 main.js 前加入固定的 Vue global build CDN；兩個 script 都放在 #app 外。
- **程式碼或操作：**

  ```text
  <script src="https://unpkg.com/vue@3.5.40/dist/vue.global.js"></script>
  <script src="main.js" defer></script>
  ```
- **預期結果：**Network 看到 Vue CDN 與 main.js；重新整理後不再因為缺少 Vue 而停止。
- **學生可能的錯誤答案：**把 CDN 放在 main.js 後面，或把 script 貼進 #app 讓執行責任混在 template 裡。
- **講師追問：**為什麼順序不是裝飾，而是 JavaScript 能不能找到 Vue 的前置條件？
- **DevTools／Console／Network／DOM 驗收：**Network 的兩個 script 請求、Console 第一個錯誤與 HTML 的 script 順序。
- **卡住時的單一檢查：**只查看 starter/files/index.html：Vue CDN 必須出現在 main.js 前面。

### Step 3：用 setup 回傳普通資料給 template

- **教學目的：**先把 createApp、setup、const、return 的責任拆開；反應式狀態延後到下一堂。
- **講師白話解釋：**先請學生說出預測，再說明這一步只處理一個責任。
- **精確檔案與區塊：**starter/files/main.js 的 createApp 與 setup 區塊
- **修改前：**Starter 的 app 已建立且有 mount，但 setup 尚未提供 title 與 description。
- **本次只修改：**在 setup 建立兩個普通字串，並用 return 交給 template；本堂不使用 ref、computed 或事件。
- **程式碼或操作：**

  ```text
  const app = VueApi.createApp({
    setup() {
      const title = "安心維護服務";
      const description = "讓訪客看懂下一步";
      return { title, description };
    },
  });
  ```
- **預期結果：**main.js 的 setup return 欄位和 template 名稱一致；下一步補上 template 後會看見兩段實際文字。
- **學生可能的錯誤答案：**只宣告 const 卻沒有 return，或直接加入還沒教過的 Vue.ref。
- **講師追問：**如果 title 沒有寫進 return，Vue 怎麼知道 template 可以使用它？請用檔案和畫面證明。
- **DevTools／Console／Network／DOM 驗收：**main.js 的 const／return 與 Console 無 ReferenceError。
- **卡住時的單一檢查：**只搜尋 setup、title、description、return 四個位置。

### Step 4：用唯一 #app 放入靜態 template

- **教學目的：**把 Vue 應用的責任範圍固定下來，並觀察插值如何從 template 變成畫面文字。
- **講師白話解釋：**先請學生說出預測，再說明這一步只處理一個責任。
- **精確檔案與區塊：**starter/files/index.html 的 main#app
- **修改前：**Starter 只有提示文字，沒有 title 與 description 的 Vue 插值。
- **本次只修改：**在唯一的 #app 內加入 h1、p 與插值；保留 script 在 #app 外，並讓 selector 與 mount 完全一致。
- **程式碼或操作：**

  ```text
  <main id="app">
    <h1>{{ title }}</h1>
    <p>{{ description }}</p>
  </main>
  ```
- **預期結果：**畫面顯示安心維護服務與說明文字；Elements 只看到一個 #app，Console 沒有錯誤。
- **學生可能的錯誤答案：**新增第二個 #app、把 script 塞進 main，或把 mount 寫成 #application。
- **講師追問：**#app 是哪一個責任邊界？如果 HTML 是 #app、JavaScript 卻 mount #application，Vue 會接手誰？
- **DevTools／Console／Network／DOM 驗收：**Elements 的唯一 #app、畫面實際文字、main.js 的 app.mount selector。
- **卡住時的單一檢查：**逐字比對 HTML 的 id 與 app.mount 的 selector，先不要重寫整份檔案。

### Step 5：在 Checkpoint 找出唯一 mount 缺口

- **教學目的：**讓學生從原始大括號症狀回到 application instance 尚未接手 DOM 的根因。
- **講師白話解釋：**先請學生說出預測，再說明這一步只處理一個責任。
- **精確檔案與區塊：**checkpoint/files/main.js 的 app 建立結尾
- **修改前：**Checkpoint 的 CDN、createApp、setup、return 與 #app 都完整，但故意沒有執行 app.mount。
- **本次只修改：**只在 main.js 最後補上 app.mount("#app")；不要複製第二個 createApp 或改 template。
- **程式碼或操作：**

  ```text
  app.mount("#app");
  ```
- **預期結果：**Checkpoint 重新整理後，原始 {{ title }} 不再出現，畫面顯示 setup 回傳的實際文字。
- **學生可能的錯誤答案：**重新建立第二個 app、把 mount 放進 setup，或只改畫面文字掩蓋真正缺口。
- **講師追問：**createApp 成功但畫面沒被 Vue 接手，哪一個生命週期步驟還沒有發生？
- **DevTools／Console／Network／DOM 驗收：**修正前後的 #app 內容、main.js 唯一的 mount 與 Console。
- **卡住時的單一檢查：**只搜尋 checkpoint/files/main.js 的 app.mount；註解不算執行碼。

### Live Lab 與階段任務對照

- Step 1 對應 **environment-setup**：examples/minimal.html 的兩個 script 與 Console／Network｜只確認 Vue CDN 在自己的 script 前面、檔案成功載入，這一步不先加入 ref、computed 或事件。；學生停點：Network 的 Vue CDN 與 main.js 成功，Console 的 typeof Vue 是 object，畫面仍由唯一的 #app 負責。；證據：Network URL／狀態碼、Console 第一個錯誤與 typeof Vue 結果。
- Step 2 對應 **starter-1**：index.html｜Vue CDN script；學生停點：Network 有 Vue CDN，main.js 不再出現 Vue is not defined。；證據：Network CDN 狀態與 Console 的 Vue 物件。
- Step 3 對應 **starter-2**：main.js｜createApp setup；學生停點：#app 顯示 setup 回傳的 title 與 description，程式不需要先使用 ref。；證據：畫面文字、main.js 的 setup return、Vue CDN 與 #app DOM。
- Step 4 對應 **starter-3**：index.html｜#app；學生停點：#app 內的 Vue template 被渲染，而不是把大括號原樣顯示。；證據：Elements 只有一個 #app，內部出現實際文字。
- Step 5 對應 **checkpoint-1**：main.js｜app.mount；學生停點：#app 內不再顯示原始 template 語法。；證據：畫面、#app DOM 與 Console 無 mount 相關錯誤。

## 6. 觀察與除錯

教師先示範故意錯誤，再要求學生依序寫下「症狀 → 證據 → 假設 → 單一修正 → 重新驗證」。本堂常見錯誤是：故意將 CDN 放在 main.js 後面或 mount 到不存在的 #app，從 Network、typeof Vue 與 Console 找原因。

## 7. 學生任務

### 教師完整示範

示範 在 index.html 載入 Vue 3 CDN，建立 app 物件並 mount 到 #app，讓 setup 回傳的服務標題與說明出現在畫面。；每次只修改一個檔案或區塊，先讓學生預測，再立即回到畫面、DOM、Console、Network 或資料結果。

### 學生跟做

把教師示範拆成三到四個 10–15 分鐘微任務：先完成入口，再完成核心修改，接著重現錯誤，最後留下驗收證據。學生必須在自己的資料夾重現，不以講師畫面成功為完成。

### 情境變體

將靜態服務介紹換成另一個服務型商家的品牌、標題與說明，保留同一個 CDN → createApp → setup → mount 順序。

### 獨立挑戰

不看 Solution，替另一個服務型商家改寫 title、description 與 status；保留 Vue CDN、唯一 #app、setup return 與 mount 的順序，提交 Network、Console、Elements 與窄版畫面證據。

### 驗收證據

Network CDN 200、typeof Vue 為 object、唯一 #app、setup 回傳值正確渲染且 Console 無 Vue 執行錯誤。學生需提交修改檔案清單、操作步驟、預期結果、實際觀察與一項可重現證據。

### 離場前回顧

請學生回答：我理解了什麼？我做出了什麼？我用什麼證據確認？下一堂會接著處理什麼？

下堂銜接：響應式渲染：下一堂才會使用 ref、computed、v-for 與 v-if 管理會改變的服務清單。

### 官方來源補充

- [Vue 官方：Quick Start／CDN](https://vuejs.org/guide/quick-start.html)
- [Vue 官方：Application API／createApp](https://vuejs.org/api/application.html)
- [Vue 官方：Application 基礎／mount](https://vuejs.org/guide/essentials/application.html)
- [MDN：script element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script)
