EP12 - 監聽器

閱讀時間約 1 分鐘
Watchers 這是啥啊?應該是幫助debug的好夥伴嗎?
它是一種用來監控數據變化並執行特定操作的功能。
雖然它可以間接地幫助除錯,
但它的主要目的是在數據變化時自動響應和執行代碼

基本範例 - Basic Example

計算屬性允許我們聲明式地計算衍生值。然而,有些情況下我們需要在狀態變更時執行「副作用」,例如,更改 DOM 或基於異步操作的結果更改另一個狀態。

使用 Composition API,我們可以使用 watch 函數在反應性狀態變更時觸發回調:

<script setup>
import { ref, watch } from 'vue'

const question = ref('')
const answer = ref('Questions usually contain a question mark. ;-)')
const loading = ref(false)

// watch 直接作用於 ref
watch(question, async (newQuestion, oldQuestion) => {
if (newQuestion.includes('?')) {
loading.value = true
answer.value = 'Thinking...'
try {
const res = await fetch('https://yesno.wtf/api')
answer.value = (await res.json()).answer
} catch (error) {
answer.value = 'Error! Could not reach the API. ' + error
} finally {
loading.value = false
}
}
})
</script>

<template>
<p>
你有問題要問嗎:
<input v-model="question" :disabled="loading" />
</p>
<p>{{ answer }}</p>
</template>

Try it in the Playground

Watch Source Types - 監聽來源類型

watch 的第一個參數可以是不同類型的反應性「來源」:可以是 ref(包括計算屬性),反應性物件,取值函數,或者多個來源組成的陣列:

const x = ref(0)
const y = ref(0)

// 單一 ref
watch(x, (newX) => {
console.log(`x 是 ${newX}`)
})

// 取值函數
watch(
() => x.value + y.value,
(sum) => {
console.log(`x + y 的和是:${sum}`)
}
)

// 多個來源的陣列
watch([x, () => y.value], ([newX, newY]) => {
console.log(`x 是 ${newX} 而 y 是 ${newY}`)
})

請注意,您不能像下面這樣監聽反應性物件的屬性:

const obj = reactive({ count: 0 })

// 這樣不行,因為我們傳遞了一個數字給 watch()
watch(obj.count, (count) => {
console.log(`Count 是:${count}`)
})

當我們使用 reactive 創建一個反應性物件時,例如 const obj = reactive({ count: 0 }),它的屬性(如 count)會被 Vue 追蹤,從而使我們可以響應它們的變化。

然而,直接將 obj.count 作為 watch 的第一個參數是無效的。這是因為 obj.count 會立即被求值並返回一個數字(如 0),而 watch 期望的是一個反應性來源,而不是一個靜態的值。

取而代之的是使用取值函數:

// 使用取值函數:
watch(
() => obj.count,
(count) => {
console.log(`Count 是:${count}`)
}
)

在這段代碼中,我們傳遞了一個箭頭函數 () => obj.countwatch。這個函數返回 obj.count 的值,而不是立即求值。這樣,Vue 可以監聽 obj.count 的變化,並在它改變時觸發回調函數 count => { console.log(Count 是:${count}) }。這樣我們就實現了對 obj.count 變化的監聽。

Deep Watchers - 深層監聽器

當你直接在反應性物件上調用 watch() 時,它會隱式地創建一個深層監聽器 ( 回調函數將會在所有巢狀變更時觸發 ):

const obj = reactive({ count: 0 })

watch(obj, (newValue, oldValue) => {
// 在巢狀屬性變更時觸發
// 注意:這裡的 `newValue` 和 `oldValue` 會相等
// 因為它們都指向同一個物件!
})

obj.count++

這應該與返回反應性物件的取值函數有所區別 ( 在後者的情況下,回調函數僅在取值函數返回一個不同的物件時才會觸發 ) :

watch(
() => state.someObject,
() => {
// 只有當 state.someObject 被替換時才會觸發
}
)

然而,你可以通過顯式地使用 deep 選項,將第二種情況強制為深層監聽器:

watch(
() => state.someObject,
(newValue, oldValue) => {
// 注意:這裡的 `newValue` 和 `oldValue` 會相等
// 除非 state.someObject 被替換
},
{ deep: true }
)

在 Vue 3.5+ 中,deep 選項也可以是一個數字,表示最大遍歷深度——也就是 Vue 應該遍歷物件巢狀屬性的層級數。

小心使用

深層監聽需要遍歷監聽物件的所有巢狀屬性,對於大型數據結構來說,這可能會非常耗費資源。僅在必要時使用,並注意其對性能的影響。

積極監聽器 - Eager Watchers​

watch 預設是延遲執行的:回調函數不會在被監聽的來源發生變更之前執行。但在某些情況下,我們可能希望立即執行相同的回調邏輯。例如,我們可能希望獲取一些初始數據,然後在相關狀態變更時重新獲取數據。

我們可以通過傳遞 immediate: true 選項,強制監聽器的回調函數立即執行:

watch(
source,
(newValue, oldValue) => {
// 立即執行,然後在 `source` 變更時再次執行
},
{ immediate: true }
)

單次監聽器 - Once Watchers​

僅支援於 Vue 3.4+。

監聽器的回調函數會在被監聽的來源變更時執行。如果你希望回調函數在來源變更時僅觸發一次,可以使用 once: true 選項。

watch(
source,
(newValue, oldValue) => {
// 當 `source` 變更時,僅觸發一次
},
{ once: true }
)

watchEffect()

在使用監聽器回調時,通常會使用相同的響應式狀態作為來源。例如,考慮以下使用監聽器在 todoId ref 變更時加載遠程資源的代碼:

const todoId = ref(1)
const data = ref(null)

watch(
todoId,
async () => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/todos/${todoId.value}`
)
data.value = await response.json()
},
{ immediate: true }
)

特別要注意的是,監聽器在回調中使用了 todoId 兩次,一次作為來源,一次在回調內使用。

這可以用 watchEffect() 來簡化。watchEffect() 允許我們自動跟踪回調的響應式依賴。上面的監聽器可以重寫為:

watchEffect(async () => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/todos/${todoId.value}`
)
data.value = await response.json()
})

在這裡,回調會立即運行,不需要指定 immediate: true。在執行期間,它會自動跟踪 todoId.value 作為依賴項(類似於計算屬性)。每當 todoId.value 變更時,回調會再次運行。使用 watchEffect(),我們不再需要顯式地將 todoId 作為來源值傳遞。

你可以查看這個 watchEffect() 和響應式數據獲取示例來了解更多。

對於只有一個依賴項的情況,watchEffect() 的好處相對較小。但對於有多個依賴項的監聽器,使用 watchEffect() 可以免去手動維護依賴項列表的負擔。此外,如果你需要監聽嵌套數據結構中的多個屬性,watchEffect() 可能比深度監聽器更有效,因為它只會跟踪回調中使用的屬性,而不是遞歸跟踪所有屬性。

提示:

watchEffect 只會在其同步執行期間跟踪依賴項。在使用異步回調時,只有在第一次 await 之前訪問的屬性會被跟踪。

watch vs. watchEffect

watchwatchEffect 都允許我們響應性地執行副作用。它們之間的主要區別在於跟踪響應式依賴的方式:

  • watch 只會跟踪顯式監聽的來源。它不會跟踪回調中訪問的任何內容。此外,只有當來源實際變更時,回調才會觸發。watch 將依賴項跟踪與副作用分開,讓我們對回調觸發的時間有更精確的控制。
  • watchEffect 則將依賴項跟踪和副作用結合到一個階段。它會自動跟踪其同步執行期間訪問的每個響應式屬性。這更方便,通常會產生更簡潔的代碼,但使其響應式依賴項不那麼明確。

副作用清理 - Side Effect Cleanup

有時,我們可能會在監聽器中執行副作用,例如異步請求:

watch(id, (newId) => {
fetch(`/api/${newId}`).then(() => {
// 回調邏輯
})
})

但如果 id 在請求完成前變更了怎麼辦?當之前的請求完成時,它仍然會使用已經過時的 ID 值觸發回調。理想情況下,我們希望能夠在 id 變更為新值時取消過時的請求。

我們可以使用 onWatcherCleanup()3.5+ API 註冊一個清理函數,該函數會在監聽器失效並即將重新運行時被調用:

import { watch, onWatcherCleanup } from 'vue'

watch(id, (newId) => {
const controller = new AbortController()

fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {
// 回調邏輯
})

onWatcherCleanup(() => {
// 中止過時的請求
controller.abort()
})
})

請注意,onWatcherCleanup 只在 Vue 3.5+ 支持,並且必須在 watchEffect 效果函數或 watch 回調函數的同步執行期間調用:你不能在異步函數的 await 語句之後調用它。

作為替代方案,一個 onCleanup 函數也會作為第三個參數傳遞給監聽器回調,並作為第一個參數傳遞給 watchEffect 效果函數:

watch(id, (newId, oldId, onCleanup) => {
// ...
onCleanup(() => {
// 清理邏輯
})
})

watchEffect((onCleanup) => {
// ...
onCleanup(() => {
// 清理邏輯
})
})

這種方法在 3.5 版本之前也適用。此外,通過函數參數傳遞的 onCleanup 綁定到監聽器實例,因此它不受 onWatcherCleanup 的同步限制。

回調刷新時機 - Callback Flush Timing​

當你修改反應性狀態時,這可能會觸發 Vue 組件更新和你創建的監聽器回調。

與組件更新類似,為了避免重複調用,使用者創建的監聽器回調會被批處理。例如,如果我們同步地將一千個項目推入一個被監聽的數組中,我們大概不希望監聽器被調用一千次。

預設情況下,監聽器的回調會在父組件更新(如果有的話)之後,在所有者組件的 DOM 更新之前被調用。這意味著如果你嘗試在監聽器回調內訪問所有者組件的 DOM,這些 DOM 會處於更新前的狀態。

後置監聽器 - Post Watchers

如果你希望在 Vue 更新所有者組件的 DOM 後再在監聽器回調內訪問它,你需要指定 flush: 'post' 選項:

watch(source, callback, {
flush: 'post'
})

watchEffect(callback, {
flush: 'post'
})

後置刷新的 watchEffect() 也有一個方便的別名 watchPostEffect()

import { watchPostEffect } from 'vue'

watchPostEffect(() => {
/* 在 Vue 更新之後執行 */
})

同步監聽器 - Sync Watchers

也可以創建一個在任何 Vue 管理的更新之前同步觸發的監聽器:

watch(source, callback, {
flush: 'sync'
})

watchEffect(callback, {
flush: 'sync'
})

同步的 watchEffect() 也有一個方便的別名 watchSyncEffect()

import { watchSyncEffect } from 'vue'

watchSyncEffect(() => {
/* 在反應性數據變更時同步執行 */
})

謹慎使用

同步監聽器沒有批處理,並且每次檢測到反應性變更時都會觸發。可以使用它們來監聽簡單的布林值,但避免用於可能被多次同步修改的數據源,例如數組。

停止監聽器 - Stopping a Watcher​

setup()<script setup> 中同步聲明的監聽器會綁定到所有者組件實例,並在所有者組件卸載時自動停止。在大多數情況下,你不需要自己擔心停止監聽器。

關鍵在於監聽器必須同步創建:如果監聽器在異步回調中創建,它將不會綁定到所有者組件,並且必須手動停止以避免記憶體洩漏。以下是示例:

<script setup>
import { watchEffect } from 'vue'

// 這個會被自動停止
watchEffect(() => {})

// ...這個則不會!
setTimeout(() => {
watchEffect(() => {})
}, 100)
</script>

要手動停止監聽器,使用返回的處理函數。這對 watchwatchEffect 都適用:

const unwatch = watchEffect(() => {})

// ...稍後,當不再需要時
unwatch()

注意,創建異步監聽器的情況應該非常少見,並且應優先選擇同步創建。如果你需要等待一些異步數據,你可以將監聽邏輯設為條件式:

// 異步加載的數據
const data = ref(null)

watchEffect(() => {
if (data.value) {
// 當數據加載完成時做些什麼
}
})
老實說看完這個章節,不知道要幹嘛?實務上?
另外副作用是啥啊?!馬上再來請教AI老師~

Q:Watch實務上應用?

在 Vue.js 中,watch 是用來監聽和響應數據變化的一個非常有用的工具。具體來說,它可以在以下幾種情況下應用:

  1. 監控數據變化
    • watch 允許你監控某些數據屬性的變化,並在這些數據變化時執行副作用(side effects)。例如,當一個用戶輸入數據時,你可以根據輸入值進行搜索或過濾操作。
  2. 執行異步操作
    • 當數據變化時,你可能需要進行異步操作,比如從 API 請求數據或提交表單。在 watch 的回調函數中,你可以進行這些異步操作。
  3. 更新其他數據
    • 你可以根據一個數據的變化來更新另一個數據。例如,當用戶選擇不同的選項時,你可能需要根據選擇的內容更新顯示的列表。
  4. 處理複雜的副作用
    • 如果你需要在數據變化時進行一些複雜的操作,如計算、數據處理、外部庫調用等,watch 提供了在數據變化時進行這些操作的機會。
  5. 清理副作用
    • 當你需要在監聽器不再需要時進行清理(如取消請求),watch 也提供了這樣的功能。例如,使用 onCleanuponWatcherCleanup 來取消未完成的請求或清理資源。

實際應用示例

  1. 自動保存用戶輸入
    const inputText = ref('')

    watch(inputText, (newText) => {
    localStorage.setItem('savedText', newText)
    })
  2. 根據用戶選擇更新顯示
    const selectedCategory = ref('')

    watch(selectedCategory, async (category) => {
    const response = await fetch(`/api/categories/${category}`)
    const items = await response.json()
    itemsList.value = items
    })
  3. 監控路由變化
    import { useRoute } from 'vue-router'

    const route = useRoute()

    watch(() => route.path, (newPath) => {
    console.log(`Route changed to: ${newPath}`)
    })
  4. 處理異步請求的副作用
    const userId = ref(1)
    const userData = ref(null)

    watch(userId, async (id) => {
    const response = await fetch(`/api/users/${id}`)
    userData.value = await response.json()
    })

總的來說,watch 在 Vue.js 中是用來處理和響應數據變化的關鍵工具,它使得你可以輕鬆地管理副作用和異步操作,並且可以靈活地根據應用的需求來處理各種複雜的情況。

Q:副作用是啥?

在編程中,副作用(side effects)指的是函數或操作在計算或執行過程中對程序的外部狀態所做的變更。這些變更可以是:

  1. 修改變量
    • 例如,修改全局變量或函數外部的變量。
  2. 執行 I/O 操作
    • 例如,讀取或寫入文件,進行網絡請求,或操作本地存儲等。
  3. 更改界面
    • 例如,更新用戶界面上的內容,或者更改 HTML 元素的樣式或屬性。
  4. 觸發事件
    • 例如,觸發用戶界面的事件或調用回調函數。
  5. 操作外部系統
    • 例如,與外部 API 交互,發送郵件,或記錄日志等。

副作用的例子

  1. 函數修改變量
    let count = 0;

    function increment() {
    count += 1; // 修改了外部變量 count
    }
  2. 網絡請求
    async function fetchData(url) {
    const response = await fetch(url); // 進行網絡請求
    const data = await response.json();
    return data;
    }
  3. 更新 DOM
    function updateElementText(elementId, text) {
    const element = document.getElementById(elementId);
    element.textContent = text; // 修改了 DOM 元素的內容
    }

在 Vue.js 中的副作用

在 Vue.js 中,副作用通常指的是對 Vue 組件內部狀態或外部系統的操作,例如:

  • 異步數據加載: 在數據變化時發起 API 請求來加載或更新數據。
  • 更新組件狀態: 根據用戶輸入或其他狀態的變化更新組件的內部狀態。
  • 修改 DOM: 根據數據變化修改 DOM,例如動態顯示或隱藏元素。

Vue.js 提供了 watchwatchEffect 來處理這些副作用,幫助你在數據變化時執行相應的操作,並且可以在適當的時候清理副作用。這樣可以確保應用程序在數據變化時能夠做出正確的響應,並保持界面和狀態的同步。

avatar-img
2會員
70內容數
分享生活趣事~
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
卡關的人生 的其他內容
在這篇文章中,探討了 Vue 組件的生命周期鉤子以及它們在不同階段的應用。每個 Vue 組件在創建時,會經歷一系列初始化步驟,這些步驟中會執行特定的生命週期鉤子函數,例如 onMounted、onUpdated 和 onUnmounted 等。這些鉤子允許開發者在組件的特定階段插入自定義代碼。
使用 v-bind 可以將 HTML 屬性、樣式或類別綁定到 Vue 的數據,實現單向數據綁定。而 v-model 則是用於表單元素的雙向數據綁定,使輸入和數據同步更新。使用 v-bind 可以讓我們綁定非字符串值,例如布爾值或對象,從而在處理更複雜的應用場景時更為靈活。
Vue.js 的事件修飾符提供了一種簡化和直觀的方式來處理事件。與傳統 JavaScript 中需要手動檢查條件和處理事件相比,Vue 的修飾符(如 .prevent、.stop、.enter)使代碼更加清晰和易於管理。這些修飾符直接在模板中指定事件行為,減少了樣板代碼,提升了可讀性。
v-for 用於渲染陣列或物件列表,支持索引和嵌套。使用 key 來提高渲染效率。v-if 和 v-for 不應同時在同一節點上使用。
Conditional Rendering 根據條件決定是否渲染元素。Vue.js 的 v-if 在條件為真時渲染,v-else-if 處理額外條件,v-show 始終渲染元素但用 CSS 控制顯示。v-if 會創建或銷毀元素,v-show 只改變顯示樣式。
這篇文章介紹了在 Vue.js 前端框架中如何有效地綁定 Class 和 Style。透過使用 v-bind 指令,使用者可以動態地切換元素的類別和內聯樣式,這不僅能夠簡化程式碼,還能防止錯誤的發生。文章中探討了物件和陣列綁定的使用情境,以及如何在組件中應用這些技術,從而提升開發效率與程式的可讀性。
在這篇文章中,探討了 Vue 組件的生命周期鉤子以及它們在不同階段的應用。每個 Vue 組件在創建時,會經歷一系列初始化步驟,這些步驟中會執行特定的生命週期鉤子函數,例如 onMounted、onUpdated 和 onUnmounted 等。這些鉤子允許開發者在組件的特定階段插入自定義代碼。
使用 v-bind 可以將 HTML 屬性、樣式或類別綁定到 Vue 的數據,實現單向數據綁定。而 v-model 則是用於表單元素的雙向數據綁定,使輸入和數據同步更新。使用 v-bind 可以讓我們綁定非字符串值,例如布爾值或對象,從而在處理更複雜的應用場景時更為靈活。
Vue.js 的事件修飾符提供了一種簡化和直觀的方式來處理事件。與傳統 JavaScript 中需要手動檢查條件和處理事件相比,Vue 的修飾符(如 .prevent、.stop、.enter)使代碼更加清晰和易於管理。這些修飾符直接在模板中指定事件行為,減少了樣板代碼,提升了可讀性。
v-for 用於渲染陣列或物件列表,支持索引和嵌套。使用 key 來提高渲染效率。v-if 和 v-for 不應同時在同一節點上使用。
Conditional Rendering 根據條件決定是否渲染元素。Vue.js 的 v-if 在條件為真時渲染,v-else-if 處理額外條件,v-show 始終渲染元素但用 CSS 控制顯示。v-if 會創建或銷毀元素,v-show 只改變顯示樣式。
這篇文章介紹了在 Vue.js 前端框架中如何有效地綁定 Class 和 Style。透過使用 v-bind 指令,使用者可以動態地切換元素的類別和內聯樣式,這不僅能夠簡化程式碼,還能防止錯誤的發生。文章中探討了物件和陣列綁定的使用情境,以及如何在組件中應用這些技術,從而提升開發效率與程式的可讀性。
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
前言 從零開始構建一個 DateTimePicker 可能看起來令人畏懼,但試想一下你將獲得的靈活性和控制力。在這個系列中,我們將逐步揭開構建過程的神秘面紗,讓您能夠創建一個完全符合需求的自定義 DateTimePicker。 本文章,屬於付費系列的文章,這篇文章,我會希望讀者可以得到的
※ 觀察者模式 定義: 觀察者模式(Observer Pattern)是一種設計模式,涉及兩個主要角色:觀察者(Observers)和被觀察者(Subject)。在這種模式中,一群觀察者訂閱並觀察某個被觀察的對象。當被觀察者的狀態發生改變時,它會通知所有觀察者,讓他們知曉並作出相應的反應。這種模
setter和getter能把狀態改變時需做的事情包裝起來,讓外部只需簡單修改參數就能達到預想的效果
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
前言 從零開始構建一個 DateTimePicker 可能看起來令人畏懼,但試想一下你將獲得的靈活性和控制力。在這個系列中,我們將逐步揭開構建過程的神秘面紗,讓您能夠創建一個完全符合需求的自定義 DateTimePicker。 本文章,屬於付費系列的文章,這篇文章,我會希望讀者可以得到的
※ 觀察者模式 定義: 觀察者模式(Observer Pattern)是一種設計模式,涉及兩個主要角色:觀察者(Observers)和被觀察者(Subject)。在這種模式中,一群觀察者訂閱並觀察某個被觀察的對象。當被觀察者的狀態發生改變時,它會通知所有觀察者,讓他們知曉並作出相應的反應。這種模
setter和getter能把狀態改變時需做的事情包裝起來,讓外部只需簡單修改參數就能達到預想的效果
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找