六角學院 - HexSchool
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Help
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    1
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    :::info 本文件連結:https://hackmd.io/o-BW3WhjRWOJjCUfqJ4YJg 此為 2025 Vue3 前端新手營課程資料,相關資源僅授權給該課程學員。 ::: # 第一週:Vue 環境、基礎概念與 Vue 指令 ## 課前說明 - 課前影音 / 錄影回放:https://courses.hexschool.com/courses/enrolled/2793063 - 每日任務:Discord 上發布 - 討論頻道:https://discord.com/channels/801807326054055996/1382641046550216705 - 每週挑戰: - HackMD 上繳交 - RPG 程式勇者: - 課程捷徑 - 課程講義 - 任務繳交(證書) - 進階任務 - 元件拆分與資料傳遞 - 最終挑戰 - Todolist 新手證書任務 - 最終挑戰 - Todolist API 整合證書任務 - 提醒老師錄影 ## Vite 基本概念 官網的安裝方式:https://vitejs.dev/guide/ 可選方式: ```docker ✔ Project name: … vue-2025-week01 ✔ Select a framework: › Vue ✔ Select a variant: › Customize with create-vue ↗ Vue.js - The Progressive JavaScript Framework ✔ 是否使用 TypeScript? … 否 ✔ 是否啟用 JSX 支援? … 否 ✔ 是否引入 Vue Router 進行單頁應用程式開發? … 否 ✔ 是否引入 Pinia 用於狀態管理? … 否 ✔ 是否引入 Vitest 用於單元測試 … 否 ✔ 是否要引入一款端對端(End to End)測試工具? › 不需要 ✔ 是否引入 ESLint 用於程式碼品質檢測? … 是 ✔ 是否引入 Prettier 用於程式碼格式化? … 是 ✔ 是否引入 Vue DevTools 7 擴充元件以協助偵錯?(試驗性功能) … 皆可 ``` - Vite 資料夾結構說明 - Vite 編譯正式版本說明 - Vite 部署說明 ### 建立新檔案 - 建立一個新的 Vue File 來進行說明 - Vue File 包含 template, script, style - ESModules 的運用 ### Ref - 基礎定義值的方式 - 取值、賦予值的方式 - 優點: - 適用全部情境 - 缺點: - 要打上 .value ### Reactive - 可以用來定義物件 - 優點: - 不用加上 .value - 缺點: - 不能重新賦予值 - 僅能用在物件型別 > 簡而言之:官方推薦 ref 到底就好了 > ## Vue 的指令集 https://hackmd.io/@hexschool/S1DJeKTdL/%2FRhud3_1PR9qv1RJyMfwUmA ![空白](https://hackmd.io/_uploads/HyiMY2DK0.png) 1. View 常用的指令 1. 資料渲染在 HTML 的內容上 - {{ }} 2. 請套用在 HTML 的屬性上 - v-for (迴圈,類似 forEach) - v-bind (HTML 屬性套用) - v-on(addEventListener) - v-if, v-else(if…else 判斷) 3. 雙向綁定 4. 觸發監聽 - Vue 初始化必須要知道的事情 - 請務必先定義資料結構 ```=javascript <script setup> import { ref } from 'vue' const inputValue = ref(3) function showValue() { alert(`你輸入的是:${inputValue.value}`) } </script> <template> <input v-bind:value="inputValue" type="text" /> <p>{{ inputValue }}</p> <p>{{ inputValue }}</p> <p>{{ inputValue }}</p> <p>{{ inputValue }}</p> <p>{{ inputValue }}</p> <button v-on:click="showValue" > 顯示輸入值 </button> <p >目前輸入:{{ inputValue }}</p> </template> <style> body { font-family: sans-serif; } </style> ``` ## v-for ```=javascript <script setup> import { ref } from 'vue' const students = ref([ { id: 's001', name: '洧杰', score: 90 }, { id: 's002', name: '小花', score: 85 }, { id: 's003', name: '阿明', score: 78 }, { id: 's004', name: '佩佩', score: 92 } ]) </script> <template> <div class="p-6"> <h2 class="text-xl font-bold mb-4">👨‍🎓 學生名單</h2> <ul> <li v-for="student in students" :key="student.id" class="mb-2 p-2 border rounded" > <p>🆔 學號:{{ student.id }}</p> <p>📛 姓名:{{ student.name }}</p> <p>📈 分數:{{ student.score }}</p> </li> </ul> </div> </template> ``` ## 情境 Code ### 範例一:BMI 計算機(V-model、v-bind、v-if 練習) :::spoiler ```=javascript <script setup> import { ref } from 'vue' // 響應式數據 const height = ref('') const weight = ref('') const bmi = ref(0) const bmiStatus = ref('') const statusColor = ref('#95a5a6') // 計算 BMI 的函數 function calculateBMI() { if (!height.value || !weight.value) { bmi.value = 0 bmiStatus.value = '' statusColor.value = '#95a5a6' return } const heightInMeters = height.value / 100 bmi.value = (weight.value / (heightInMeters * heightInMeters)).toFixed(1) // 計算狀態 const bmiValue = parseFloat(bmi.value) if (bmiValue < 18.5) { bmiStatus.value = '體重過輕' statusColor.value = '#3498db' } else if (bmiValue < 24) { bmiStatus.value = '正常範圍' statusColor.value = '#27ae60' } else if (bmiValue < 27) { bmiStatus.value = '體重過重' statusColor.value = '#f39c12' } else { bmiStatus.value = '肥胖' statusColor.value = '#e74c3c' } } </script> <template> <div class="container"> <h1>BMI 計算器</h1> <div class="form-group"> <label>身高 (公分):</label> <!-- v-model 雙向綁定 --> <input v-model="height" type="number" placeholder="請輸入身高" > </div> <div class="form-group"> <label>體重 (公斤):</label> <!-- v-model 雙向綁定 --> <input v-model="weight" type="number" placeholder="請輸入體重" > </div> <!-- 顯示輸入的數值 --> <div class="input-display"> <p>您輸入的身高: {{ height || '未輸入' }} 公分</p> <p>您輸入的體重: {{ weight || '未輸入' }} 公斤</p> </div> <!-- 計算按鈕 --> <div class="button-group"> <button @click="calculateBMI" :disabled="!height || !weight" > 計算 BMI </button> </div> <!-- BMI 結果顯示 --> <div class="result" v-if="bmi > 0"> <h2>您的 BMI 值: {{ bmi }}</h2> <!-- v-bind 綁定樣式 --> <h3 :style="{ color: statusColor }">{{ bmiStatus }}</h3> </div> <!-- BMI 參考標準 --> <div class="reference"> <h4>BMI 參考標準:</h4> <ul> <li :style="{ color: '#3498db' }">過輕: &lt; 18.5</li> <li :style="{ color: '#27ae60' }">正常: 18.5 - 23.9</li> <li :style="{ color: '#f39c12' }">過重: 24 - 26.9</li> <li :style="{ color: '#e74c3c' }">肥胖: ≥ 27</li> </ul> </div> </div> </template> <style scoped> .container { max-width: 400px; margin: 50px auto; padding: 20px; font-family: Arial, sans-serif; } h1 { text-align: center; color: #2c3e50; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; font-weight: bold; } input { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px; } .input-display { background-color: #f8f9fa; padding: 10px; border-radius: 4px; margin: 15px 0; } .input-display p { margin: 5px 0; font-size: 14px; color: #666; } .button-group { text-align: center; margin: 20px 0; } button { padding: 12px 24px; font-size: 16px; background-color: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover:not(:disabled) { background-color: #2980b9; } button:disabled { background-color: #95a5a6; cursor: not-allowed; } .result { text-align: center; margin: 20px 0; padding: 15px; background-color: #f0f0f0; border-radius: 4px; } .reference { margin-top: 30px; padding: 15px; background-color: #f8f9fa; border-radius: 4px; } .reference h4 { margin-top: 0; color: #2c3e50; } .reference ul { list-style: none; padding: 0; } .reference li { padding: 2px 0; font-weight: bold; } </style> ``` ::: ### 範例二:字數倒數計算器(computed) :::spoiler ```=JavaScript <script setup> import { ref, computed } from 'vue' // 響應式數據 const userInput = ref('') const maxLength = ref(50) // 計算剩餘字數 (使用 computed) const remainingChars = computed(() => { return maxLength.value - userInput.value.length }) // 清空輸入 const clearInput = () => { userInput.value = '' } </script> <template> <div class="container"> <h1>字數倒數計算器</h1> <!-- 設定字數限制 --> <div class="setting-group"> <label>字數限制:</label> <!-- v-model 雙向綁定 --> <input v-model="maxLength" type="number" min="10" max="200" > </div> <!-- 文字輸入區 --> <div class="input-group"> <label>請輸入文字:</label> <!-- v-model 雙向綁定文字內容 --> <textarea v-model="userInput" placeholder="開始輸入您的文字..." rows="4" ></textarea> </div> <!-- 顯示統計資訊 --> <div class="info-box"> <p>已輸入: {{ userInput.length }} 字</p> <p>字數限制: {{ maxLength }} 字</p> <!-- v-bind 根據剩餘字數改變顏色 --> <p :style="{ color: remainingChars >= 0 ? 'green' : 'red' }"> 剩餘: {{ remainingChars }} 字 </p> </div> <!-- 即時預覽 --> <div class="preview-box"> <h3>預覽:</h3> <div class="preview-text"> {{ userInput || '您輸入的文字會顯示在這裡...' }} </div> </div> <!-- 操作按鈕 --> <div class="button-area"> <!-- v-bind 控制按鈕是否可點擊 --> <button @click="clearInput" :disabled="userInput.length === 0" > 清空 </button> <button :disabled="remainingChars < 0" :style="{ backgroundColor: remainingChars < 0 ? 'gray' : '#007bff' }" > {{ remainingChars < 0 ? '字數超過!' : '確定' }} </button> </div> </div> </template> <style scoped> .container { max-width: 500px; margin: 30px auto; padding: 20px; font-family: Arial, sans-serif; } h1 { text-align: center; color: #333; } .setting-group, .input-group { margin-bottom: 20px; } label { display: block; margin-bottom: 5px; font-weight: bold; } input[type="number"] { width: 100px; padding: 8px; border: 1px solid #ccc; border-radius: 4px; } textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; font-size: 16px; resize: vertical; } .info-box { background-color: #f5f5f5; padding: 15px; border-radius: 4px; margin-bottom: 20px; } .info-box p { margin: 5px 0; font-size: 16px; } .preview-box { border: 1px solid #ddd; border-radius: 4px; padding: 15px; margin-bottom: 20px; } .preview-box h3 { margin-top: 0; color: #555; } .preview-text { min-height: 50px; padding: 10px; background-color: #f9f9f9; border-radius: 4px; white-space: pre-wrap; } .button-area { display: flex; gap: 10px; } button { flex: 1; padding: 10px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; color: white; } button:first-child { background-color: #6c757d; } button:disabled { cursor: not-allowed; opacity: 0.6; } button:hover:not(:disabled) { opacity: 0.9; } </style> ``` ::: | 差異重點 | **Computed(推薦)** | **普通函式 (methods)** | |-----------|--------------------|------------------------| | **快取機制** | ✅ 內建快取,依賴資料沒變就重用結果 | ❌ 無快取,每次呼叫都重新執行 | | **重新計算時機** | 只有相依 reactive 資料變動才重新計算 | 每次模板重新渲染或手動呼叫都會執行 | | **用途定位** | 適合做「資料衍生」:如 **總價、格式化日期** | 適合做「觸發動作」:如 **按鈕事件、API 呼叫** | | **在模板中的寫法** | 像變數:`{{ totalPrice }}` | 像函式:`@click="addToCart()"` | | **效能/可讀性** | 複雜或昂貴運算 ➜ 效能佳、語意清楚 | 簡單即時計算 ➜ 寫法直觀、上手快 | ## 關注點分離 Vue.js 的關注點分離強調將視圖層 (UI) 與資料層 (Data) 分開。視圖層使用模板語法來描述界面,而資料層使用 `data` 物件管理狀態,並通過雙向數據綁定 (`v-model`) 使視圖和資料同步更新。這種分離提升了代碼的可維護性和重用性,使開發更高效。 將畫面轉變為資料: ``` <table> <thead> <tr> <th>代辦事項名稱</th> <th>到期日</th> <th>是否已完成</th> </tr> </thead> <tbody> <tr> <td>購買雜貨</td> <td>2024-07-30</td> <td>是</td> </tr> <tr> <td>完成報告</td> <td>2024-08-01</td> <td>否</td> </tr> <tr> <td>清理房間</td> <td>2024-07-28</td> <td>是</td> </tr> <tr> <td>計劃假期</td> <td>2024-08-05</td> <td>否</td> </tr> <tr> <td>處理稅務</td> <td>2024-08-10</td> <td>否</td> </tr> </tbody> </table> ``` ## 作業: 餐點管理工具 - Level 1:將菜單轉為資料格式 - Level 2:可以重新設定菜單的庫存數量 - Level 3(挑戰):可以重新設定品項名稱 作業需求: 1. 將以下的表格轉為使用資料,並使用 Vue 進行渲染。 2. 數量的部分可以點擊,並且調整庫存數量。 3. 庫存數量不會低於 0。 4. 新增欄位 “編輯”,按下後可以修改該欄位的品項名稱(按下確認後執行更換) ```html <table> <thead> <tr> <th scope="col">品項</th> <th scope="col">描述</th> <th scope="col">價格</th> <th scope="col">庫存</th> </tr> </thead> <tbody> <tr> <td>珍珠奶茶</td> <td><small>香濃奶茶搭配QQ珍珠</small></td> <td>50</td> <td><button>-</button>20<button>+</button></td> </tr> <tr> <td>冬瓜檸檬</td> <td><small>清新冬瓜配上新鮮檸檬</small></td> <td>45</td> <td><button>-</button>18<button>+</button></td> </tr> <tr> <td>翡翠檸檬</td> <td><small>綠茶與檸檬的完美結合</small></td> <td>55</td> <td><button>-</button>34<button>+</button></td> </tr> <tr> <td>四季春茶</td> <td><small>香醇四季春茶,回甘無比</small></td> <td>45</td> <td><button>-</button>10<button>+</button></td> </tr> <tr> <td>阿薩姆奶茶</td> <td><small>阿薩姆紅茶搭配香醇鮮奶</small></td> <td>50</td> <td><button>-</button>25<button>+</button></td> </tr> <tr> <td>檸檬冰茶</td> <td><small>檸檬與冰茶的清新組合</small></td> <td>45</td> <td><button>-</button>20<button>+</button></td> </tr> <tr> <td>芒果綠茶</td> <td><small>芒果與綠茶的獨特風味</small></td> <td>55</td> <td><button>-</button>18<button>+</button></td> </tr> <tr> <td>抹茶拿鐵</td> <td><small>抹茶與鮮奶的絕配</small></td> <td>60</td> <td><button>-</button>20<button>+</button></td> </tr> </tbody> </table> ``` 解答連結: - 執行範例:https://www.casper.tw/2024-vue-homework/#/week1 - 原始碼:https://github.com/Wcc723/2024-vue-homework/blob/main/src/views/Week1View.vue - 作業繳交連結:https://hackmd.io/9Q-arVa6RdGjeBoF2XPHMQ ## AI 分享 ## 公司目前導入 AI 細節 1. 有提供 ChatGPT 2. 無法針對全面性去解決,但可以部分單點內容去調整 3. 如何有效降低腦力負擔

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully