前端面經-VUE3篇--vue3基礎知識(一)插值表達式、ref、reactive

?一、計算屬性(computed)

計算屬性(Computed Properties)是 Vue 中一種特殊的響應式數據,它能基于已有的響應式數據動態計算出新的數據。

計算屬性有以下特性:

  • 自動緩存:只有當它依賴的響應式數據發生變化時,才會重新計算。

  • 響應式更新:依賴的數據變化后,會自動觸發計算屬性重新計算。

  • 簡化模板:在模板中使用計算屬性可以減少復雜邏輯,讓模板更清晰、易讀。

簡單來說:

計算屬性是基于其他響應式數據而自動計算得到的值,且具有緩存和響應式的特性。

1、計算屬性的基本用法

<script setup>
import { ref, computed } from 'vue'// 響應式數據
const firstName = ref('Tom')
const lastName = ref('Jerry')// 計算屬性(根據響應式數據動態計算)
const fullName = computed(() => {return `${firstName.value} ${lastName.value}`
})
</script><template><div>{{ fullName }}</div> <!-- 顯示:Tom Jerry -->
</template>

注意默認計算屬性是只讀的,但也可以定義成可寫。當你嘗試修改一個計算屬性時,你會收到一個運行時警告。只在某些特殊場景中你可能才需要用到“可寫”的屬性,你可以通過同時提供 getter 和 setter 來創建:

<script setup>
import { ref, computed } from 'vue'const firstName = ref('John')
const lastName = ref('Doe')const fullName = computed({// getterget() {return firstName.value + ' ' + lastName.value},// setterset(newValue) {// 注意:我們這里使用的是解構賦值語法[firstName.value, lastName.value] = newValue.split(' ')}
})
</script>

?現在當你再運行?fullName.value = 'John Doe'?時,setter 會被調用而?firstName?和?lastName?會隨之更新。

注意,computed()里面不接受任何的參數,我們看到里面有一個回調函數,這個回調函數本質上是getter函數

  • 之前版本(<3.4),這個 getter 函數沒有參數。

  • 從 3.4 開始,這個 getter 函數可以接受一個參數:就是上一次計算屬性的計算結果。

簡單來說:

如果需要,可以通過訪問計算屬性的 getter 的第一個參數來獲取計算屬性返回的上一個值:

<script setup>
import { ref, computed } from 'vue'const count = ref(2)// 這個計算屬性在 count 的值小于或等于 3 時,將返回 count 的值。
// 當 count 的值大于等于 4 時,將會返回滿足我們條件的最后一個值
// 直到 count 的值再次小于或等于 3 為止。
const alwaysSmall = computed((previous) => {if (count.value <= 3) {return count.value}return previous
})
</script>

?如果你正在使用可寫的計算屬性的話:

<script setup>
import { ref, computed } from 'vue'const count = ref(2)const alwaysSmall = computed({get(previous) {if (count.value <= 3) {return count.value}return previous},set(newValue) {count.value = newValue * 2}
})
</script>

?2、計算屬性與方法(methods)的詳細區別

兩者區別如下:

對比維度計算屬性(computed)方法(methods)
緩存機制有緩存,僅數據變化才重新計算無緩存,每次調用都會執行
調用方式不需要括號調用,像屬性一樣使用需要括號調用,明確為函數
適用場景基于響應式數據的計算處理事件或顯式調用的場景
性能開銷性能較高(緩存優化)性能較低(頻繁調用時)

計算屬性與方法性能差異分析

假設模板多次渲染對比:

  • 計算屬性

    <div>{{ doubleCount }}</div>
    <div>{{ doubleCount }}</div>
    <div>{{ doubleCount }}</div>
    
    • 只計算一次,緩存結果。

  • 方法調用

    <div>{{ getDoubleCount() }}</div>
    <div>{{ getDoubleCount() }}</div>
    <div>{{ getDoubleCount() }}</div>
    
    • 每次都調用一次,共調用3次,性能浪費。

因此,對于頻繁使用但數據不頻繁變化的場景,建議使用計算屬性

3、計算屬性什么時候不能用?

計算屬性適用于:

  • 同步、快速的計算邏輯

  • 無副作用的計算(純函數)。

計算屬性不適合:

  • 異步邏輯(如請求數據)。

  • 執行副作用(修改其他數據、DOM 操作)。

?二、監聽屬性

在 Vue 中,監聽屬性(Watcher) 是一種響應式機制,用于監測響應式數據的變化:

  • 當你想在數據發生變化時執行某些邏輯(如發送請求、更新數據或執行某些副作用)時,就可以使用監聽屬性。

  • 監聽屬性通過 Vue 提供的 watch()watchEffect() 函數實現。

簡單來說:

監聽屬性讓你能夠對數據變化做出反應,執行一些副作用或異步操作。

1、監聽屬性的基本用法(watch)

<script setup>
import { ref, watch } from 'vue'const count = ref(0)// 監聽 count 的變化
watch(count, (newValue, oldValue) => {console.log(`count變化了:從${oldValue}到${newValue}`)
})
</script><template><button @click="count++">增加 ({{ count }})</button>
</template>

count 的值改變時,watch 會自動觸發,執行回調函數。

監聽多個數據:?

const firstName = ref('Tom')
const lastName = ref('Jerry')// 同時監聽 firstName 和 lastName
watch([firstName, lastName], ([newFirst, newLast], [oldFirst, oldLast]) => {console.log(`名字變化了:${oldFirst} ${oldLast} => ${newFirst} ${newLast}`)
})

2、監聽屬性的參數與選項(高級用法)

🔹 監聽屬性的函數簽名:watch(source, callback, options)

  • source: 需要監聽的響應式數據,可以是單個或多個。可以是不同形式的“數據源”:它可以是一個 ref (包括計算屬性)、一個響應式對象、一個?getter 函數、或多個數據源組成的數組:

  • callback: 數據變化時執行的回調函數。

  • options: 可選參數,控制監聽器行為。

🔹 常用的監聽選項(options):

選項含義默認值
immediate是否立即執行一次監聽回調false
deep是否深度監聽對象內部屬性變化false
flush控制監聽器回調的執行時機'pre'

?深度監聽(deep)到底是什么?

  • 默認情況下,Vue 的監聽器只能監聽對象引用本身的變化(比如替換對象)。

  • 使用 deep: true 時,能監聽對象或數組內部屬性或元素的變化。

const user = ref({ name: 'Tom', age: 18 })// 默認淺監聽(只能監聽整個對象變化)
watch(user, () => {console.log('淺監聽:user變化了')
})user.value.age = 19 // ?不會觸發淺監聽(對象引用未變)
user.value = { name: 'Jerry', age: 19 } // ??觸發// 深度監聽(對象內部屬性變化也會觸發)
watch(user, () => {console.log('深監聽:user變化了')
}, { deep: true })user.value.age = 20 // ??觸發深度監聽

?監聽屬性的執行時機(flush)

flush 控制監聽回調的執行時機:

flush 值含義使用場景
pre默認值,組件更新之前執行大多數情況
post組件更新之后執行需要訪問更新后的DOM時
sync同步觸發,數據變化立即執行非常特殊情況

3、watch vs watchEffect 的區別

在 Vue 中,watch()watchEffect() 都用于響應式地執行一些副作用操作(如發起請求、改變 DOM),但二者的追蹤數據依賴方式不同:

特性watch()watchEffect()
如何追蹤依賴手動顯式指定要監聽的數據(明確)自動追蹤回調中訪問的數據(隱式)
首次執行默認不立即執行,需手動開啟自動立即執行一次
控制粒度精確控制監聽的數據項,控制更細自動追蹤所有訪問的響應式數據,更靈活
適用場景明確知道監聽什么數據變化數據依賴較多或復雜,更希望自動追蹤

?舉個簡單例子,監聽單個明確的數據:

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 被顯式聲明為監聽的源。

  • 回調函數只在明確的源數據(todoId)改變時觸發。

  • 必須用 { immediate: true } 來立即執行一次,否則首次不會執行。

1、?watchEffect() 如何簡化上面的例子?

?

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

特點:

  • 自動立即執行一次,無需手動指定 { immediate: true }

  • 無需手動指定監聽源,回調函數內的所有響應式數據訪問(這里是 todoId.value)會自動被 Vue 跟蹤。

  • 一旦被跟蹤的數據變化(例如:todoId.value 改變),回調會自動再次執行。

?2、watchEffect() 的依賴跟蹤原理(關鍵):

watchEffect() 會自動追蹤回調函數在同步執行時訪問的所有響應式數據。
但有個重要提示:

如果回調是異步函數,那么只有在第一個 await 之前訪問的數據才會被追蹤!

watchEffect(async () => {console.log(todoId.value) // ? 被追蹤,因為在 await 之前訪問const response = await fetch('...')console.log(someOtherRef.value) // ? 不被追蹤,因為在 await 之后訪問
})

原因是:

  • Vue 只能追蹤同步執行階段訪問的數據。

  • 在異步操作完成后的回調內訪問的數據不會被 Vue 追蹤。

3、watchEffect() 在實際場景中的優勢:

優勢一:自動跟蹤多個數據源(不必手動指定):

假如你有多個響應式數據:

const firstName = ref('Tom')
const lastName = ref('Jerry')watchEffect(() => {console.log(`Name: ${firstName.value} ${lastName.value}`)
})Vue 自動監控 firstName 和 lastName。無論哪個改變,都會觸發回調函數。使用 watch() 則必須手動指定數據源:
watch([firstName, lastName], () => {console.log(`Name: ${firstName.value} ${lastName.value}`)
})
優勢二:更精細地跟蹤對象屬性(比深監聽高效):

假如你有復雜對象:

const user = ref({name: 'Tom',age: 20,address: { city: 'Shanghai', street: 'Main St' }
})watchEffect(() => {console.log(`User city: ${user.value.address.city}`)
})watchEffect() 只監聽了對象的部分屬性 (address.city),高效、精準。如果用深監聽 (watch(user, ..., { deep: true })),會監聽所有屬性的變化,性能可能較差。

4、什么時候用 watch()?什么時候用 watchEffect()

場景推薦方式理由
明確知道監聽的數據源? 使用 watch()明確指定,粒度精準
多個數據源或依賴復雜? 使用 watchEffect()自動跟蹤,代碼更簡潔、更靈活
動態數據請求或復雜副作用? watchEffect()自動監聽,省去手動指定煩惱

4、監聽屬性的常見使用場景

場景示例
數據變化請求API表單值變化時重新獲取數據
數據變化存儲數據自動保存用戶輸入
執行副作用數據變化時更新DOM或執行動畫

5、監聽屬性的注意事項?

  • 避免無限循環:

    watch(count, (val) => {count.value++ // ?? 無限循環,不要這樣做
    })
    
  • 不要監聽非響應式數據(監聽無效):

    const plain = { name: 'Tom' }
    watch(plain, () => {}) // ? 無效
    
  • 使用深監聽時注意性能問題(深監聽成本較高):

    watch(obj, () => {}, { deep: true }) // 謹慎使用
    

    注意,你不能直接偵聽響應式對象的屬性值,例如、

const obj = reactive({ count: 0 })// 錯誤,因為 watch() 得到的參數是一個 number
watch(obj.count, (count) => {console.log(`Count is: ${count}`)
})

?這里需要用一個返回該屬性的 getter 函數:

// 提供一個 getter 函數
watch(() => obj.count,(count) => {console.log(`Count is: ${count}`)}
)

6、副作用清理

在 Vue 中,所謂的副作用通常指:

  • 異步請求(如 API 請求)

  • 定時器 (setTimeoutsetInterval)

  • DOM 操作、監聽事件

  • 其他非純函數的邏輯

這些操作不是立即完成的,可能會在未來某個時刻繼續執行

?為什么需要副作用清理?

以 API 請求為例:假設我們有一個監聽器監聽 id:
watch(id, (newId) => {fetch(`/api/${newId}`).then(() => {console.log('請求完成,當前ID:', newId)})
})

可能的問題:

當你快速修改 id

  • 請求 1 (/api/1) 發出后,還未完成。

  • 請求 2 (/api/2) 立即發出。

  • 如果請求 2 的響應比請求 1 快,那么請求 1 的響應(較慢)回來時,結果是過時的,但還是會被處理。

我們想要的:

  • 當數據變化時,上一個異步請求應被取消或忽略,不再執行后續邏輯。

為了解決這個問題,Vue 提供了副作用清理機制

副作用清理函數 (onCleanup())

Vue 3.0 開始,Vue 提供了一個清理機制,稱為 onCleanup

watch(id, (newId, oldId, onCleanup) => {const controller = new AbortController()fetch(`/api/${newId}`, { signal: controller.signal }).then((res) => res.json()).then((data) => {console.log('請求結果:', data)})onCleanup(() => {controller.abort() // 取消上一個請求})
})

含義解釋:

  • 每次監聽的數據 (id) 變化時:

    • 先調用上一次注冊的 onCleanup 清理函數

    • 然后再執行新一次監聽回調。

  • 因此,上一次的異步請求會自動終止,避免過時請求的結果被錯誤處理。

?watchEffect() 中的副作用清理

watchEffect((onCleanup) => {const timer = setInterval(() => {console.log('定時執行')}, 1000)onCleanup(() => {clearInterval(timer) // 清理定時器})
})

原理相同:

  • 每次響應式數據變化重新執行副作用之前,先調用清理函數。

  • 確保副作用(定時器、請求等)不重疊,避免內存泄漏或數據錯亂。

從 Vue 3.5 版本開始,引入了新 API:onWatcherCleanup():?

import { watch, onWatcherCleanup } from 'vue'watch(id, (newId) => {const controller = new AbortController()fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {console.log('請求完成:', newId)})onWatcherCleanup(() => {controller.abort() // 取消上一個請求})
})

特點:

  • 不再需要第三個參數 onCleanup

  • 可以獨立地在監聽器或 watchEffect() 回調函數內調用清理函數。

?使用限制:

  • 必須在同步階段調用,不可放在 await 之后。

  • 因此,必須在異步操作之前注冊。

正確用法(同步調用):watch(id, (newId) => {const controller = new AbortController()onWatcherCleanup(() => controller.abort()) // 同步調用,正確!fetch(`/api/${newId}`, { signal: controller.signal })
})? 錯誤用法(異步調用):watch(id, async (newId) => {const controller = new AbortController()await someAsyncOperation()onWatcherCleanup(() => controller.abort()) // ? 錯誤!異步調用

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79124.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79124.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79124.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據結構6 · BinaryTree二叉樹模板

代碼函數功能順序如下&#xff1a; 1&#xff1a;destroy&#xff1a;遞歸刪除樹 2&#xff1a;copy&#xff1a;復制二叉樹 3&#xff1a;preOrder&#xff1a;遞歸前序遍歷 4&#xff1a;inOrder&#xff1a;遞歸中序遍歷 5&#xff1a;postOrder&#xff1a;遞歸后續遍…

C++/SDL進階游戲開發 —— 雙人塔防游戲(代號:村莊保衛戰 13)

&#x1f381;個人主頁&#xff1a;工藤新一 &#x1f50d;系列專欄&#xff1a;C面向對象&#xff08;類和對象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;終會照亮我前方的路 &#x1f389;歡迎大家點贊&#x1f44d;評論&#x1f4dd;收藏?文章 文章目錄 十…

強化學習之基于無模型的算法之時序差分法

2、時序差分法(TD) 核心思想 TD 方法通過 引導值估計來學習最優策略。它利用當前的估計值和下一個時間步的信息來更新價值函數&#xff0c; 這種方法被稱為“引導”&#xff08;bootstrapping&#xff09;。而不需要像蒙特卡羅方法那樣等待一個完整的 episode 結束才進行更新&…

AE/PR模板 100個現代文字標題動態排版效果動畫 Motion Titles

Motion Titles是一個令人驚艷的AE/PR模板&#xff0c;提供了100個現代文字標題的動態排版效果動畫。這些動畫效果能夠為你的項目增添視覺沖擊力和專業感&#xff0c;為文字標題注入活力和動感。該模板適用于Adobe After Effects CC或更高版本以及Adobe Premiere Pro 2020或更高…

【AI提示詞】二八法則專家

提示說明 精通二八法則&#xff08;帕累托法則&#xff09;的廣泛應用&#xff0c;擅長將其應用于商業、管理、個人發展等領域&#xff0c;深入理解其在不同場景中的具體表現和實際意義。 提示詞 # Role: 二八法則專家## Profile - language: 中文 - description: 精通二八法…

前端八股 CSS 1

盒子模型 進行布局時將所有元素表示為一個個盒子box padding margin border content content&#xff1a;盒子內容 待顯示的文本和圖像 padding&#xff1a;內邊距&#xff0c;內容和border之間的空間&#xff0c;不能為負數&#xff0c;受bkc影響 border:邊框&#xff0c…

組件通信-$attrs

概述&#xff1a;$attrs用于實現當前組件的父組件&#xff0c;向當前組件的子組件通信&#xff08;爺→孫&#xff09;。 具體說明&#xff1a;$attrs是一個對象&#xff0c;包含所有父組件傳入的標簽屬性。 注意&#xff1a;$attrs會自動排除props中聲明的屬性(可以認為聲明過…

jdk開啟https詳細步驟

要在 JDK 中啟用 HTTPS&#xff0c;您可以按照以下詳細步驟進行操作&#xff1a; 生成密鑰庫和證書&#xff1a; 首先&#xff0c;您需要生成一個密鑰庫&#xff08;keystore&#xff09;和證書&#xff0c;可以使用 keytool 工具來生成。以下是使用 keytool 生成密鑰庫和證書的…

文章四《深度學習核心概念與框架入門》

文章4&#xff1a;深度學習核心概念與框架入門——從大腦神經元到手寫數字識別的奇幻之旅 引言&#xff1a;給大腦裝個"GPU加速器"&#xff1f; 想象一下&#xff0c;你的大腦如果能像智能手機的GPU一樣快速處理信息會怎樣&#xff1f;這正是深度學習的終極目標&…

關于CSDN創作的常用模板內容

&#x1f91f;致敬讀者 &#x1f7e9;感謝閱讀&#x1f7e6;笑口常開&#x1f7ea;生日快樂?早點睡覺 &#x1f4d8;博主相關 &#x1f7e7;博主信息&#x1f7e8;博客首頁&#x1f7eb;專欄推薦&#x1f7e5;活動信息 文章目錄 好文評論新文推送 &#x1f4c3;文章前言 &…

linux的信號量初識

Linux下的信號量(Semaphore)深度解析 在多線程或多進程并發編程的領域中&#xff0c;確保對共享資源的安全訪問和協調不同執行單元的同步至關重要。信號量&#xff08;Semaphore&#xff09;作為經典的同步原語之一&#xff0c;在 Linux 系統中扮演著核心角色。本文將深入探討…

《Android 應用開發基礎教程》——第十一章:Android 中的圖片加載與緩存(Glide 使用詳解)

目錄 第十一章&#xff1a;Android 中的圖片加載與緩存&#xff08;Glide 使用詳解&#xff09; &#x1f539; 11.1 Glide 簡介 &#x1f538; 11.2 添加 Glide 依賴 &#x1f538; 11.3 基本用法 ? 加載網絡圖片到 ImageView&#xff1a; ? 加載本地資源 / 文件 / UR…

AE模板 300個故障干擾損壞字幕條標題動畫視頻轉場預設

這個AE模板提供了300個故障干擾損壞字幕條標題動畫視頻轉場預設&#xff0c;讓您的視頻具有炫酷的故障效果。無論是預告片、宣傳片還是其他類型的視頻&#xff0c;這個模板都能帶給您令人驚嘆的故障運動標題效果。該模板無需任何外置插件或腳本&#xff0c;只需一鍵點擊即可應用…

在 Python 中,以雙下劃線開頭和結尾的函數(如 `__str__`、`__sub__` 等)

在 Python 中&#xff0c;以雙下劃線開頭和結尾的函數&#xff08;如 __str__、__sub__ 等&#xff09;被稱為特殊方法&#xff08;Special Methods&#xff09;或魔術方法&#xff08;Magic Methods&#xff09;。它們確實是 Python 內置的&#xff0c;用于定義類的行為&#…

git問題記錄-如何切換歷史提交分支,且保留本地修改

問題記錄 我在本地編寫了代碼&#xff0c;突然想查看之前提交的代碼&#xff0c;并且想保留當前所在分支所做的修改 通過git stash對本地的代碼進行暫存 使用git checkout <commit-hash>切換到之前的提交記錄。 查看完之后我想切換回來&#xff0c;恢復暫存的本地代碼…

Github開通第三方平臺OAuth登錄及Java對接步驟

調研起因&#xff1a; 準備搞AI Agent海外項目&#xff0c;有相當一部分用戶群體是程序員&#xff0c;所以當然要接入Github這個全球最大的同性交友網站了&#xff0c;讓用戶使用Github賬號一鍵完成注冊或登錄。 本教程基于Web H5界面進行對接&#xff0c;同時也提供了spring-…

期刊、出版社、索引數據庫

image 1、研究人員向期刊或者會議投稿&#xff0c;交注冊費和相應的審稿費等相關費用[1]&#xff1b; 2、會議組織者和期刊聯系出版社&#xff0c;交出版費用&#xff1b; 3、出版社將論文更新到自己的數據庫中&#xff0c;然后將數據庫賣給全世界各大高校或企業&#xff1b; 4…

Transformer 模型及深度學習技術應用

近年來&#xff0c;隨著卷積神經網絡&#xff08;CNN&#xff09;等深度學習技術的飛速發展&#xff0c;人工智能迎來了第三次發展浪潮&#xff0c;AI技術在各行各業中的應用日益廣泛。 注意力機制&#xff1a;理解其在現代深度學習中的關鍵作用&#xff1b; Transformer模型…

zynq7035的arm一秒鐘最多可以支持觸發多少次中斷

一、概述 1.關于zynq7035的ARM處理器一秒能夠支持多少次中斷觸發&#xff0c;需要綜合來考慮。需要確定ARM處理器的參數&#xff0c;目前zynq7000系列&#xff0c;使用的雙核Cortex-A9處理器。其中主頻大概在500MHZ~1GHZ左右&#xff0c;不同的用戶配置的主頻可能稍微有差別。 …

數據結構與算法:圖論——最短路徑

最短路徑 先給出一些leetcode算法題&#xff0c;以后遇見了相關題目再往上增加 最短路徑的4個常用算法是Floyd、Bellman-Ford、SPFA、Dijkstra。不同應用場景下&#xff0c;應有選擇地使用它們&#xff1a; 圖的規模小&#xff0c;用Floyd。若邊的權值有負數&#xff0c;需要…