總目標: 在 Day 36-42 理解組件化開發的思想,熟練掌握 Vue 組件的注冊、Props、Events、v-model、Slots、Provide/Inject 等核心概念和實踐,能夠構建可復用和易于維護的組件結構。
- 所需資源:
- Vue 3 官方文檔 (組件基礎): https://cn.vuejs.org/guide/essentials/component-basics.html
- Vue 3 官方文檔 (組件深入): https://cn.vuejs.org/guide/components/registration.html (此鏈接及后續部分覆蓋注冊、Props、Events、v-model、Slots、Provide/Inject、動態與異步組件)
- 你的 Vue 3 實踐項目(作為實踐環境)。
Day 36: 組件基礎與注冊 (~3 小時)
-
本日目標: 理解組件化思想,學會創建和注冊 Vue 單文件組件(SFC),并在應用中使用它們。
-
學習計劃:
-
番茄時鐘 1 (25 分鐘工作 + 5 分鐘休息):
- 內容: 為什么需要組件化?
- 活動: 閱讀官方文檔“組件基礎”引言,理解組件化帶來的好處(代碼復用、可維護性、關注點分離)。思考如何將一個復雜的頁面拆分成獨立的邏輯塊。
- 思考: 在你日常看到的網頁中,哪些部分可以被抽象成可復用的組件?
- 休息: 短暫休息。
-
番茄時鐘 2 (25 分鐘工作 + 5 分鐘休息):
- 內容: 創建單文件組件 (.vue)。
- 活動: 閱讀官方文檔“單文件組件”部分。了解
.vue
文件結構(<template>
,<script setup>
,<style>
)。創建一個新的.vue
文件,編寫最基礎的組件代碼(包含一個模板和一個簡單的<script setup>
塊)。 - 實踐: 在你的項目
src/components
目錄下創建一個MyComponent.vue
文件,添加基礎模板和空的 script/style 塊。 - 休息: 短暫休息。
-
番茄時鐘 3 (25 分鐘工作 + 5 分鐘休息):
- 內容: 局部組件注冊。
- 活動: 閱讀官方文檔“組件注冊”部分關于局部注冊的內容。理解在
<script setup>
中導入組件后,無需額外注冊步驟,直接在模板中使用即可。 - 實踐: 在
src/App.vue
或其他父組件中,導入你創建的MyComponent.vue
,并在父組件的<template>
中使用<MyComponent/>
標簽。運行項目,確認子組件被渲染。 - 休息: 短暫休息。
-
番茄時鐘 4 (25 分鐘工作 + 5 分鐘休息):
- 內容: 全局組件注冊 (了解)。
- 活動: 閱讀官方文檔關于全局注冊的內容。理解全局注冊的組件可以在應用中的任何地方直接使用,無需導入。了解它的優缺點(方便但可能導致打包體積過大,且依賴不明確),以及為什么在現代構建工具下更推薦局部注冊。
- 實踐: (可選,了解概念為主) 如果你的項目使用
main.js
作為入口,嘗試在main.js
中使用app.component()
方法注冊一個組件。 - 休息: 短暫休息。
-
總結與回顧 (10-15 分鐘):
- 回顧組件化思想、
.vue
文件結構。 - 鞏固局部組件注冊是現代 Vue 開發的主要方式。
- 確保你能在父組件中成功使用子組件。
- 回顧組件化思想、
-
Day 37: 組件通信 - Props (~3 小時)
-
本日目標: 學習如何使用 Props 實現父組件向子組件傳遞數據。
-
所需資源: Vue 3 官方文檔 (Props): https://cn.vuejs.org/guide/components/props.html
-
學習計劃:
-
番茄時鐘 1 (25 分鐘工作 + 5 分鐘休息):
- 內容: Props 的概念與聲明 (
defineProps
)。 - 活動: 閱讀官方文檔“Props”部分。理解 Props 是組件接收外部數據的接口,數據流是單向的(父 -> 子)。學習在子組件的
<script setup>
中使用defineProps
宏來聲明組件接受的 Props。 - 實踐: 在 Day 36 創建的
MyComponent.vue
中,使用defineProps(['message'])
聲明一個message
prop。 - 休息: 短暫休息。
- 內容: Props 的概念與聲明 (
-
番茄時鐘 2 (25 分鐘工作 + 5 分鐘休息):
- 內容: 在模板和腳本中使用 Props。
- 活動: 理解聲明的 Props 可以直接在子組件的模板中像普通變量一樣使用,在腳本中則可以通過
defineProps
的返回值訪問(如果需要)。 - 實踐: 在
MyComponent.vue
的<template>
中顯示{{ message }}
。在父組件使用子組件時,通過屬性綁定:message="'Hello from Parent!'"
傳遞數據。 - 休息: 短暫休息。
-
番茄時鐘 3 (25 分鐘工作 + 5 分鐘休息):
- 內容: Props 類型校驗 (基礎)。
- 活動: 閱讀官方文檔關于 Props 類型校驗的部分。學習如何為 Props 指定預期的 JavaScript 數據類型(String, Number, Boolean, Array, Object, Date, Function, Symbol)。理解類型校驗失敗時會發出控制臺警告(僅在開發模式)。
- 實踐: 將
defineProps(['message'])
改為defineProps({ message: String })
。嘗試傳遞非字符串類型的數據,觀察警告。為其他數據類型添加校驗。 - 休息: 短暫休息。
-
番茄時鐘 4 (25 分鐘工作 + 5 分鐘休息):
- 內容: Props 類型校驗 (必填與默認值)。
- 活動: 學習如何將 Prop 標記為必填 (
required: true
) 以及如何為 Prop 設置默認值 (default: ...
)。理解不同數據類型的默認值寫法(特別是對象/數組默認值需要通過工廠函數返回)。 - 實踐: 將
message
Prop 設為必填。為另一個 Prop 設置默認值。設置一個對象 Prop,并使用工廠函數設置默認值。 - 休息: 短暫休息。
-
總結與回顧 (10-15 分鐘):
- 回顧 Props 的概念、聲明、使用。
- 鞏固 Props 類型校驗的各種方式(類型、必填、默認值)。
- 確保理解 Props 的單向數據流原則:子組件不應直接修改 Prop 的值。
-
Day 38: 組件通信 - Events (~3 小時)
-
本日目標: 學習如何使用 Events 實現子組件向父組件傳遞信息或通知。
-
所需資源: Vue 3 官方文檔 (Events): https://cn.vuejs.org/guide/components/events.html
-
學習計劃:
-
番茄時鐘 1 (25 分鐘工作 + 5 分鐘休息):
- 內容: Events 的概念與聲明 (
defineEmits
)。 - 活動: 閱讀官方文檔“組件事件”部分。理解事件用于子組件向父組件“發出信號”。學習在子組件的
<script setup>
中使用defineEmits
宏來聲明組件會發出的事件。聲明 emitted 事件有助于文檔化和校驗。 - 實踐: 在一個子組件(例如一個按鈕組件
MyButton.vue
)中,使用defineEmits(['click'])
聲明一個click
事件。 - 休息: 短暫休息。
- 內容: Events 的概念與聲明 (
-
番茄時鐘 2 (25 分鐘工作 + 5 分鐘休息):
- 內容: 觸發事件 (
$emit
)。 - 活動: 學習在子組件的方法中或通過 DOM 事件監聽器來調用
$emit
函數觸發聲明的事件。 - 實踐: 在
MyButton.vue
中,給<button>
元素添加一個@click="$emit('click')"
。 - 休息: 短暫休息。
- 內容: 觸發事件 (
-
番茄時鐘 3 (25 分鐘工作 + 5 分鐘休息):
- 內容: 在父組件監聽事件 (
v-on
或@
)。 - 活動: 閱讀官方文檔關于監聽事件的部分。理解在父組件中使用子組件時,可以通過
v-on:
或其縮寫@
來監聽子組件發出的事件,并綁定一個父組件的方法來響應。 - 實踐: 在父組件中使用
MyButton
,并添加@click="handleButtonClick"
,在父組件的<script setup>
中定義handleButtonClick
方法(例如彈出一個 alert)。 - 休息: 短短休息。
- 內容: 在父組件監聽事件 (
-
番茄時鐘 4 (25 分鐘工作 + 5 分鐘休息):
- 內容: 傳遞參數與事件校驗 (可選)。
- 活動: 學習在
$emit
時可以傳遞額外的參數給父組件的事件處理函數。了解defineEmits
也可以接收一個對象進行更詳細的事件校驗(可選,但了解一下)。 - 實踐: 修改
MyButton.vue
,在$emit('click', 'some data', 123)
時傳遞一些參數。在父組件的handleButtonClick(data1, data2)
方法中接收并打印這些參數。 - 休息: 短暫休息。
-
總結與回顧 (10-15 分鐘):
- 回顧 Events 的概念、聲明 (
defineEmits
)、觸發 ($emit
)、監聽 (@
)。 - 鞏固如何通過事件傳遞數據從子到父。
- 確保你能構建一個父子組件,父組件向子組件傳文本 (Props),子組件點擊按鈕向父組件發送消息 (Events)。
- 回顧 Events 的概念、聲明 (
-
Day 39: Props/Events 實踐與 v-model
應用于組件 (~3 小時)
-
本日目標: 通過實踐鞏固 Props 和 Events 的用法,并學習如何使你的自定義組件支持
v-model
。 -
所需資源:
- Vue 3 官方文檔 (Props): https://cn.vuejs.org/guide/components/props.html
- Vue 3 官方文檔 (Events): https://cn.vuejs.org/guide/components/events.html
- Vue 3 官方文檔 (在組件上使用 v-model): https://cn.vuejs.org/guide/components/v-model.html
-
學習計劃:
-
番茄時鐘 1 (25 分鐘工作 + 5 分鐘休息):
- 內容: Props 與 Events 綜合實踐。
- 活動: 構建一個更復雜的父子組件交互示例。例如:一個列表組件 (父) 渲染多個列表項組件 (子)。父組件通過 Props 將數據傳遞給每個列表項。每個列表項有一個刪除按鈕,點擊時通過 Events 通知父組件刪除對應的項(傳遞項的 ID 或索引)。
- 實踐: 實現上述列表與列表項的示例。
- 休息: 短暫休息。
-
番茄時鐘 2 (25 分鐘工作 + 5 分鐘休息):
- 內容:
v-model
在組件上的概念。 - 活動: 閱讀官方文檔“在組件上使用 v-model”部分。理解
v-model
在組件上是 Prop 和 Event 的語法糖。默認情況下,v-model
綁定到modelValue
Prop 并監聽update:modelValue
事件。 - 思考: 為什么 Vue 需要這個語法糖?它簡化了什么?
- 休息: 短暫休息。
- 內容:
-
番茄時鐘 3 (25 分鐘工作 + 5 分鐘休息):
- 內容: 實現組件的
v-model
支持。 - 活動: 學習如何在你的自定義輸入組件中接收
modelValue
Prop,并在需要更新值時觸發update:modelValue
事件。 - 實踐: 創建一個簡單的自定義文本輸入組件 (
MyInput.vue
)。聲明modelValue
Prop (defineProps(['modelValue'])
) 和update:modelValue
事件 (defineEmits(['update:modelValue'])
)。在內部<input>
元素的@input
事件中,調用$emit('update:modelValue', $event.target.value)
。 - 休息: 短暫休息。
- 內容: 實現組件的
-
番茄時鐘 4 (25 分鐘工作 + 5 分鐘休息):
- 內容: 使用自定義
v-model
組件。 - 活動: 在父組件中,使用你創建的
MyInput
組件,并使用v-model
綁定一個響應式變量。 - 實踐: 在父組件中定義一個
text = ref('')
。在模板中使用<MyInput v-model="text"/>
。在父組件模板中顯示{{ text }}
,觀察輸入框和顯示是否同步。 - 休息: 短暫休息。
- 內容: 使用自定義
-
總結與回顧 (10-15 分鐘):
- 鞏固 Props 和 Events 是組件通信的基礎方式。
- 理解
v-model
在組件上的實現原理和使用方法。 - 確保你的自定義輸入組件能夠成功支持
v-model
。
-
Day 40: 組件內容分發 - Slots (~3 小時)
-
本日目標: 學習如何使用 Slots 實現父組件向子組件插入內容,使組件更具靈活性和可復用性。
-
所需資源: Vue 3 官方文檔 (Slots): https://cn.vuejs.org/guide/components/slots.html
-
學習計劃:
-
番茄時鐘 1 (25 分鐘工作 + 5 分鐘休息):
- 內容: Slots 的概念與默認插槽。
- 活動: 閱讀官方文檔“插槽”部分。理解 Slots 是組件模板中的占位符,允許父組件將任意內容“注入”到子組件的指定位置。學習默認插槽
<slot></slot>
。 - 實踐: 創建一個容器組件 (
MyCard.vue
),其中有一個<slot></slot>
占位符。在父組件使用MyCard
時,在<MyCard>...</MyCard>
標簽中間放入一些 HTML 內容,觀察這些內容如何出現在子組件<slot>
的位置。 - 休息: 短暫休息。
-
番茄時鐘 2 (25 分鐘工作 + 5 分鐘休息):
- 內容: 具名插槽 (
<slot name="...">
)。 - 活動: 學習如何使用具名插槽,通過
name
屬性區分不同的插槽。學習在父組件中使用v-slot:name
或#name
指令來指定內容要插入到哪個具名插槽。 - 實踐: 修改
MyCard.vue
,添加<slot name="header"></slot>
和<slot name="footer"></slot>
。在父組件中,使用<template #header>...</template>
和<template #footer>...</template>
將內容分別插入到頭部和尾部插槽。 - 休息: 短暫休息。
- 內容: 具名插槽 (
-
番茄時鐘 3 (25 分鐘工作 + 5 分鐘休息):
- 內容: 作用域插槽 (Scoped Slots) 的概念。
- 活動: 閱讀官方文檔關于作用域插槽的內容。理解作用域插槽允許子組件向父組件的插槽內容暴露數據。這使得父組件可以根據子組件提供的數據來決定如何渲染插槽內容。
- 思考: 作用域插槽解決什么問題?(父組件需要使用子組件內部的數據來控制渲染)。
- 休息: 短暫休息。
-
番茄時鐘 4 (25 分鐘工作 + 5 分鐘休息):
- 內容: 使用作用域插槽 (
<slot :propName="...">
,v-slot:name="slotProps"
)。 - 活動: 學習在子組件的
<slot>
標簽上綁定屬性來暴露數據(這些屬性會作為對象傳遞給父組件的插槽)。學習在父組件的<template v-slot:name="slotProps">
或<template #name="slotProps">
中通過slotProps
對象訪問子組件暴露的數據。 - 實踐: 修改一個組件(例如列表項組件),在
<slot>
標簽上綁定一項數據,如<slot :item="itemData"></slot>
。在父組件使用時,通過<template #default="{ item }"> {{ item.name }} </template>
的方式接收并使用這個數據來渲染列表項內容。 - 休息: 短暫休息。
- 內容: 使用作用域插槽 (
-
總結與回顧 (10-15 分鐘):
- 回顧 Slots 的概念、默認插槽、具名插槽。
- 重點鞏固作用域插槽的用法和它解決的問題。
- 確保你能構建一個包含不同類型插槽的組件,并在父組件中正確使用它們。
-
Day 41: 組件通信 - Provide/Inject 與 Slots 實踐 (~3 小時)
-
本日目標: 學習 Provide/Inject 實現跨層級組件通信,并通過實踐鞏固 Slots 用法。
-
所需資源:
- Vue 3 官方文檔 (Slots): https://cn.vuejs.org/guide/components/slots.html
- Vue 3 官方文檔 (Provide / Inject): https://cn.vuejs.org/guide/components/provide-inject.html
-
學習計劃:
-
番茄時鐘 1 (25 分鐘工作 + 5 分鐘休息):
- 內容: Slots 綜合實踐。
- 活動: 結合默認插槽、具名插槽和作用域插槽,構建一個更復雜的組件示例。例如:一個模態框(Modal)組件,包含頭部、內容和底部插槽,內容插槽是一個作用域插槽,可以暴露模態框的開關狀態給父組件,讓父組件決定顯示什么內容。
- 實踐: 實現一個 Modal 組件,包含頭部(具名)、內容(作用域)和底部(具名)插槽。
- 休息: 短暫休息。
-
番茄時鐘 2 (25 分鐘工作 + 5 分鐘休息):
- 內容: Provide/Inject 的概念。
- 活動: 閱讀官方文檔“Provide / Inject”部分。理解 Provide/Inject 提供了一種“依賴注入”的方式,允許一個祖先組件向其所有后代提供數據,無論層級有多深。理解它解決了 Prop Drilling(逐層傳遞 Prop)的問題。
- 思考: 什么場景下 Provide/Inject 比 Props 更合適?(數據需要在多個層級深的后代組件中使用)。
- 休息: 短暫休息。
-
番番茄時鐘 3 (25 分鐘工作 + 5 分鐘休息):
- 內容: 使用
provide
提供數據。 - 活動: 學習在祖先組件的
<script setup>
中使用provide
函數來提供數據。提供的數據可以是靜態值,也可以是響應式數據。通常推薦提供響應式數據(使用ref
或reactive
)。 - 實踐: 創建一個頂層組件(祖先),導入
provide
和ref
。使用provide('my-key', myData)
提供一個響應式數據myData = ref('Initial Data')
。 - 休息: 短暫休息。
- 內容: 使用
-
番茄時鐘 4 (25 分鐘工作 + 5 分鐘休息):
- 內容: 使用
inject
注入數據。 - 活動: 學習在后代組件的
<script setup>
中使用inject
函數來注入祖先組件提供的數據。理解inject
函數的第一個參數是提供時使用的 key,第二個參數是找不到提供數據時的默認值。 - 實踐: 創建一個中間組件和一個底層組件(后代)。在底層組件中,導入
inject
,使用const injectedData = inject('my-key', 'Default Value')
注入數據。在模板中顯示{{ injectedData }}
。在頂層組件和底層組件之間嵌套中間組件。觀察數據是否成功注入。 - 休息: 短暫休息。
- 內容: 使用
-
總結與回顧 (10-15 分鐘):
- 鞏固 Slots(默認、具名、作用域)的用法。
- 理解 Provide/Inject 的概念和它解決的問題(Prop Drilling)。
- 掌握
provide
和inject
的基本使用。
-
Day 42: 動態組件、異步組件與綜合回顧 (~3.5 小時)
-
本日目標: 學習動態加載和異步加載組件的技術,并對組件化開發的各種知識進行全面回顧。
-
所需資源:
- Vue 3 官方文檔 (動態組件): https://cn.vuejs.org/guide/components/dynamic-async.html#dynamic-components
- Vue 3 官方文檔 (異步組件): https://cn.vuejs.org/guide/components/dynamic-async.html#async-components
-
學習計劃:
-
番茄時鐘 1 (25 分鐘工作 + 5 分鐘休息):
- 內容: 動態組件 (
<component :is="...">
)。 - 活動: 閱讀官方文檔關于動態組件的部分。理解
<component :is="...">
允許你根據一個響應式變量的值來動態切換要渲染的組件。 - 實踐: 創建幾個簡單的組件(例如
Home.vue
,About.vue
,Contact.vue
)。在父組件中定義一個響應式變量currentComponent = ref('Home')
。在模板中使用<component :is="currentComponent"></component>
。添加按鈕,點擊時修改currentComponent
的值,觀察渲染的組件是否切換。 - 休息: 短暫休息。
- 內容: 動態組件 (
-
番茄時鐘 2 (25 分鐘工作 + 5 分鐘休息):
- 內容: 動態組件與
<KeepAlive>
(了解)。 - 活動: 簡單了解
<KeepAlive>
組件可以緩存動態組件的實例,避免在切換時銷毀和重建。理解它對性能的潛在影響。 - 實踐: (可選) 將
<component :is="...">
包裹在<KeepAlive>
中,觀察組件切換時是否會重新執行生命周期鉤子(如果緩存,則不會)。 - 休息: 短暫休息。
- 內容: 動態組件與
-
番茄時鐘 3 (25 分鐘工作 + 5 分鐘休息):
- 內容: 異步組件 (
defineAsyncComponent
) 的概念。 - 活動: 閱讀官方文檔關于異步組件的部分。理解異步組件用于延遲加載組件的代碼塊,直到需要渲染時才從服務器加載。這有助于減小初始打包體積,提高應用的首屏加載速度(代碼分割)。
- 思考: 異步組件主要解決什么問題?
- 休息: 短暫休息。
- 內容: 異步組件 (
-
番茄時鐘 4 (25 分鐘工作 + 5 分鐘休息):
- 內容: 使用
defineAsyncComponent
。 - 活動: 學習使用
defineAsyncComponent
函數來定義一個異步組件。它接收一個加載函數,通常是動態導入 (import()
)。了解異步組件可以配合 Suspense 或具有加載、錯誤、超時狀態處理(雖然這些可能不是本次計劃的重點,但要知曉)。 - 實踐: 將之前創建的一個不太重要的組件(例如某個設置頁面的組件)改為異步組件:
const AsyncComponent = defineAsyncComponent(() => import('./components/MyHeavyComponent.vue'))
。在父組件中使用<AsyncComponent/>
。 - 休息: 短短休息。
- 內容: 使用
-
番茄時鐘 5 (25 分鐘工作 + 5 分鐘休息):
- 內容: 綜合回顧:組件通信方式總結。
- 活動: 花時間回顧并總結所有學過的組件間通信方式:Props (父->子)、Events (子->父)、v-model (父<->子,語法糖)、Slots (父->子,內容分發)、Provide/Inject (祖先->后代)。思考它們各自的適用場景和優缺點。
- 思考: 對于一個特定的通信需求,你會選擇哪種方式?為什么?
- 休息: 短暫休息。
-
番茄時鐘 6 (25 分鐘工作 + 5 分鐘休息):
- 內容: 綜合實踐與問題解答。
- 活動: 嘗試構建一個稍復雜的示例,結合使用多種通信方式。例如:一個簡單的用戶列表,使用
v-for
渲染,每個列表項是子組件,子組件通過 Props 接收用戶數據,通過 Events 刪除用戶。列表頂部有一個過濾輸入框,父組件通過 Props 傳遞過濾文本給子組件,或者子組件通過 Events 向上報告過濾文本。或者嘗試用 Slots 渲染列表項的不同部分。遇到問題,查閱文檔或回顧之前的學習內容。 - 實踐: 選擇一個綜合實踐場景并開始實現。
- 休息: 短暫休息。
-
最終回顧 (10-15 分鐘):
- 確保對組件化開發的整體流程和各個核心概念有了清晰的認識。
- 回顧掌握程度,標記薄弱環節以便后續加強。
- 思考如何將這些知識應用到實際項目開發中。
-
掌握檢查:
- 在 Day 42 結束時,你應該能夠:
- 獨立創建和使用局部注冊的 Vue 單文件組件。
- 使用
defineProps
聲明 Props 并進行類型校驗、設置必填和默認值。 - 使用
defineEmits
聲明事件,通過$emit
觸發事件,并在父組件使用@
監聽事件和接收參數。 - 實現一個支持
v-model
的自定義表單輸入組件。 - 使用默認插槽、具名插槽和作用域插槽來靈活分發內容。
- 使用
provide
和inject
實現跨層級的數據傳遞。 - 理解
<component :is="...">
實現動態組件切換。 - 理解
defineAsyncComponent
實現異步組件加載的概念。 - 能夠根據不同的需求場景,選擇合適的組件間通信方式。