第六節:帶你全面理解vue3 淺層響應式API: shallowRef, shallowReactive, shallowReadonly

前言

前面兩章,給大家講解了vue3ref, reactive,readonly創建響應式數據的API, 以及常用的計算屬性computed, 偵聽器watch,watchEffect的使用

其中reactive, ref, readonly創建的響應式數據都是深層響應.

而本章主要給大家講解以上三個API 對應的創建淺層響應式數據的 API, 即shallowRef, shallowReactive, shallowReadonly

1. shallowRef

shallowRefref 淺層作用形式。其實就是淺層響應式

shalloRef的使用方式和ref()完全相同, 不同的只是vue對數據響應式處理的不同:

  • ref創建的數據, 如果有深層, 比如參數是一個對象, 對象的屬性就是深層, 參數對象會被vue通過reactive處理為深層響應
  • shallowRef創建數據, 只有頂層的value屬性具有響應性, 深層的數據不具有響應性, 會原因返回, 即vue不會遞歸的將深層數據通過reactive處理, 而是原樣存儲和暴露.

1.1. 類型

我們先看一下shallowRefAPI 的類型簽名, 其簽名如下:

function shallowRef<T>(value: T): ShallowRef<T>interface ShallowRef<T> {value: T
}

通過簽名可以簡單的看出, shallowRefAPI 接收一個參數, 返回一個具有value屬性的對象, 且value屬性的類型和參數類型相同.

1.2. ref 和shallowRef 處理原始數據類型

接下會通過示例帶大家看一下refshallowRef 在處理原始數據類型的有什么不同.

示例代碼:

<template><div><h3>shallowRef</h3><div>{{ count }}</div><div>{{ count2 }}</div><button @click="change">修改數據源</button></div>
</template><script lang="ts">
import { defineComponent, ref, shallowRef } from 'vue'export default defineComponent({setup() {const count = ref(0)const count2 = shallowRef(0)// 控制臺輸出 ref, shallowRef 創建的數據consollog("count", count);console.log("count2", count2);// 修改數據const change = () => {// count.value++count2.value++}return { count, count2, change }}
})
</script>

控制臺輸出結果

img

通過代碼的運行結果, 你可以看出,

在參數為基本數據類型的情況下, refshallowRef創建的響應式數據在使用上完全一樣, value屬性都具有響應性

通過控制臺輸出結果, 你會發現refshallowRef創建的ref對象極度相似,
如果你閱讀過源碼, 你就會明白, ref, shallowRef返回對象是通過同一個類實例化的對象.因此兩個實例對象具有相同的屬性. 但是有一個屬性__v_isShallow屬性值不同, 因為vue通過這個屬性來區分是ref還是shallowRef創建的對象.

這里不對源碼實現做過多闡述, 如果你對源碼感興趣, 可以關注我的vue3源碼專欄


1.3. ref 和shallowRef 處理深層對象

refshallowRef 在處理深層對象就會有所不同:

  • ref函數在處理深層對象時, 深層對象會被vue自動調用reactive包裹成響應式數據,
  • shallowRef函數在處理深層對象時, vue不同將深層對象包裹為響應式對象, 也就是說shallowRef只有.value屬性值才具有響應性, 深層對象不具有響應性

示例:

<template><div><h3>shallowRef</h3><div>{{ count }}</div><div>{{ count2 }}</div><button @click="change">修改數據源</button></div>
</template><script lang="ts">
import { defineComponent, ref, shallowRef } from 'vue'export default defineComponent({setup() {const count = ref({ count: 0 })const count2 = shallowRef({ count: 0 })// 控制輸出 ref, shallowRef 對于參數為對象時創建的ref 對象console.log('count', count)console.log('count2', count2)// 修改數據const change = () => {// count.value.count++// 不會觸發響應式// count2.value.count++// count2 是shallowRef數據// shallowRef 數據只有通過.value 整體修改時才會觸發響應式count2.value = { count: 3 }}return { count, count2, change }}
})
</script>

控制臺輸出:

img

通過控制臺輸出ref, shallowRef 創建的響應數據, 以及示例的運行結果, 會發現:

  • shallowRef在參數為深層對象時, 創建的ref數據, value值就是參數原對象, 不具有響應性
  • refvalue屬性值, 是vue調用reactive函數包裹成的Proxy代理對象, 即響應式數據

因此, 你可以理解shallowRefref 淺層響應式的API, 只有通過.value修改數據才會觸發響應式, 深層對象沒有通過reactive包裹, 因此深層操作數據不具有響應式

shallowRef() 常常用于對大型數據結構的性能優化或是與外部的狀態管理系統集成。


2. shallowReactive

shallowRefref關系相似,

shallowReactivereactive淺層作用形式。就是創建具有淺層響應性的數據


2.1. shallowReactive 類型

首先,我們先看一下shallowReactive類型簽名, 簽名如下:

function shallowReactive<T extends object>(target: T): T

通過簽名可以看出, shallowReactive函數接收一個對象作為參數, 返回類型與參數類型相同

2.2. shallowReactive 淺層響應式

reactive() 不同,shallowReactive創建響應對象沒有深層級的轉換:一個淺層響應式對象里只有根級別的屬性是響應式的, 深層對象不會被vue自動包裝為響應對象.

示例:

<template><div><h3>shallowReactive</h3><div>{{ user }}</div><div>{{ user2 }}</div><button @click="change">修改數據源</button></div>
</template><script lang="ts">
import { defineComponent, reactive, shallowReactive } from 'vue'export default defineComponent({setup() {const user = reactive({ name: '張三', age: 18, friend: { name: '李四' } })const user2 = shallowReactive({ name: '張三', age: 18, friend: { name: '李四' } })// 控制臺輸出reactive, shallowReactive 創建的深層對象console.log("reactive friend", user.friend);console.log("shallowReactive friend", user2.friend);// 修改數據const change = () => {// 1. reactive, shallowReactive 在處理第一層對象屬性時// 都會觸發響應式// user.name = "王五"  // 修改 reactive// user2.name = "王五"  // 修改 shallowReactive// 2. 操作深度屬性,shallowReactive 不會觸發響應性// user.friend.name = '王五'  // 修改 reactiveuser2.friend.name = '王五'  // 修改 shallowReactive  不觸發響應式}return { user, user2, change }}
})
</script>

控制臺輸出結果:

img

通過控制臺輸出結果, 你應該已經看出:

  • reactive創建的響應數據(代理對象) 深層對象也會自動的調用reactive函數, 創建為響應數據
  • shallowReactive創建淺層響應數據, 其深層對象就是原樣的不同對象, 不具有響應性.

運行結果也可以看出, 修改shallowReactive深層對象的數據, 頁面是不會有任何變化的.因為不具有響應性.

2.3. shallowReactive 深層ref 數據不會自動解包

shallowReactive()函數創建一個淺層響應式對象里只有根級別的屬性是響應式的。

也可以說shallowReactive()函數創建的數據是非深度監聽, 只會包裝第一個對象, 這也就意味著深層的ref數據不會被自動解包.

因為shallowReactive 深層數據的存儲是原樣存儲, 不會包裹為深度響應式,

示例:

<template><div><h3>shallowReactive</h3><div>{{ user }}</div><div>{{ user2 }}</div><button @click="change">修改數據源</button></div>
</template><script lang="ts">
import { defineComponent, reactive, ref, shallowReactive } from 'vue'export default defineComponent({setup() {const count = ref(10)const user = reactive({ name: '張三', age: 18, count })const count2 = ref(20)const user2 = shallowReactive({ name: '張三', age: 18, count: count2 })// 修改數據const change = () => {// 1. reactive 操作深層ref 數據時,自動解包// 此時修改user.count 數據時不用添加.value// user.count = 20  // 修改 reactive// 2. shallowReactive 操作深層ref 數據時,不會自動解包// 此時修改user2.count 數據時必須使用.valueuser2.count.value = 40  // 修改 shallowReactive}return { user, user2, change }}
})
</script>

2.4. shallowReactive與shallowRef 使用比較

  1. 一般情況下使用refreactive即可
  2. 如果有一個對象數據, 結構比較深, 但只有一層對象的屬性變化會觸發響應, 使用shallowReactive
  3. 如果有一個對象數據, 后面會產生新的對象來整體替換觸發響應式, 使用shallowRef

3. shallowReadonly

shallowReadonlyreadonly淺層作用形式。只有第一層是只讀的,深層不是只讀屬性,

也可以這么理解, 只有第一層的對象屬性不能修改值, 但深層的數據是可以修改的, 是非深層只讀

3.1. shallowReadonly 淺層只讀

shallowReadonly在使用上與readonly完全相同, 區域在于:

  • readonly() 創建只讀代理, 如果有深層對象, 深層對象也會自動調用readonly處理為只讀代理
  • shallowReadonly 創建的是淺層只讀代理, 也就是深層對象不會自動調用readonly包裹, 所以深層對象是非只讀的, 即可以修改的. 也就意味著只有根層級的屬性變為了只讀。

示例:

<template><div><h3>shallowReadonly</h3><div>{{ user }}</div><div>{{ user2 }}</div><button @click="change">修改數據源</button></div>
</template><script lang="ts">
import { defineComponent, readonly, ref, shallowReadonly } from 'vue'export default defineComponent({setup() {const user = readonly({ name: '張三', age: 18, friend: { name: '李四' } })const user2 = shallowReadonly({ name: '張三', age: 18, friend: { name: '李四' } })// 修改數據const change = () => {// readonly 為深層只讀, 修改任何一層屬性值都是不合法// user.name = '王五'// user.friend.name = '王五'// shallowReadonly 只有第一層會被轉為只讀, 深層屬性會原樣存儲,不是只讀的// user2.name = '王五'  // shallowReadonly 第一層修改報錯,因為是只讀的// shallowReadonly 修改生成不會報錯,// 但也不會觸發響應性, 因為原樣存儲就是一個普通對象user2.friend.name = '王五'}return { user, user2, change }}
})
</script>

3.2. shallowReadonly 處理深層ref不會自動解包

因為shallowReadonly 深層數據的存儲是原樣存儲, 不會自動調用shallowReadonly轉為只讀, 因此對于深層的ref 的數據不會被自動解包了。

示例:

<template><div><h3>shallowReadonly</h3><div>{{ user }}</div><div>{{ user2 }}</div></div>
</template><script lang="ts">
import { defineComponent, readonly, ref, shallowReadonly } from 'vue'export default defineComponent({setup() {const count = ref(10)const user = readonly({ name: '張三', age: 18, count })const count2 = ref(20)const user2 = shallowReadonly({ name: '張三', age: 18, count: count2 })// readonly 處理深層數據為ref 數據時, 會自動解包,不用添加.valueconsole.log('user.count', user.count)// shallowReadonly 獲取深層ref 數據時必須添加.value, 因為不會自動解包console.log('user2.count', user2.count.value)return { user, user2 }}
})
</script>

4. 結語

至此, 就把shallowRef, shallowReactive,shallowReadonly給大家講解完了, 這三個API使用上還是相對較少. 大家要理解這些API的使用原理, 工作中根據情況選擇不同的API .

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

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

相關文章

Java面試題:Executor框架在Java并發編程中扮演什么角色?如何使用它?

在Java并發編程中&#xff0c;Executor框架扮演著核心角色&#xff0c;它提供了一種高級的、線程安全的機制來異步執行任務。Executor框架的主要目的是將任務的提交與任務的執行分離&#xff0c;從而簡化了多線程編程的復雜性。 Executor框架的角色&#xff1a; 任務與線程分離…

持續總結中!2024年面試必問 20 道 Redis面試題(八)

上一篇地址&#xff1a;持續總結中&#xff01;2024年面試必問 20 道 Redis面試題&#xff08;七&#xff09;-CSDN博客 十五、使用過Redis做異步隊列么&#xff0c;你是怎么用的&#xff1f; Redis作為一個高性能的鍵值存儲系統&#xff0c;非常適合用來實現異步隊列。異步隊…

【STM32單片機】----實現LED燈閃爍實戰

&#x1f3a9; 歡迎來到技術探索的奇幻世界&#x1f468;?&#x1f4bb; &#x1f4dc; 個人主頁&#xff1a;一倫明悅-CSDN博客 ?&#x1f3fb; 作者簡介&#xff1a; C軟件開發、Python機器學習愛好者 &#x1f5e3;? 互動與支持&#xff1a;&#x1f4ac;評論 &…

【機器學習-23】關聯規則(Apriori)算法:介紹、應用與實現

在現代數據分析中&#xff0c;經常需要從大規模數據集中挖掘有用的信息。關聯規則挖掘是一種強大的技術&#xff0c;可以揭示數據中的隱藏關系和規律。本文將介紹如何使用Python進行關聯規則挖掘&#xff0c;以幫助您發現數據中的有趣模式。 一、引言 1. 簡要介紹關聯規則學習…

[處理器芯片]-5 超標量CPU實現之ALU

ALU&#xff08;Arithmetic Logic Unit&#xff0c;算術邏輯單元&#xff09;&#xff0c;是CPU執行單元中最主要的組成部分。 1 主要功能 算術運算&#xff1a;執行加法、減法、乘法和除法等算術運算。 邏輯運算&#xff1a;執行與、或、非、異或等邏輯運算。 移位運算&am…

動態路由實驗—OSPF

動態路由協議實驗-------OSPF 鏈路狀態路由選擇協議又被稱為最短路徑優先協議&#xff0c;它基SPF&#xff08;shortest path first &#xff09;算法 實驗要求&#xff1a;各個PC之間能夠互通 1.四臺PC配置如下 PC1 PC2 PC3 PC4 2.配置各個交換機的口子的IP R1 <HUAWE…

Room注解無效原因

在Android項目中&#xff0c;如果父模塊使用Kotlin&#xff0c;而子模塊用Java編寫&#xff0c;并且在子模塊中使用了Room庫&#xff0c;那么你會發現需要使用kapt而不是annotationProcessor來處理Room注解。這里有幾個原因和背景知識&#xff1a; 1. 項目配置的影響 父模塊的…

spiderfoot一鍵掃描IP信息(KALI工具系列九)

目錄 1、KALI LINUX簡介 2、spiderfoot工具簡介 3、在KALI中使用spiderfoot 3.1 目標主機IP&#xff08;win&#xff09; 3.2 KALI的IP 4、命令示例 4.1 web訪問 4.2 掃描并進行DNS解析 4.3 全面掃描 5、總結 1、KALI LINUX簡介 Kali Linux 是一個功能強大、多才多…

YOLOv8+PyQt:實時檢測(攝像頭、視頻)

1.YOLO&#xff1a;CPU實時檢測&#xff08;攝像頭、視頻&#xff09;https://blog.csdn.net/qq_45445740/article/details/106557451 2.YOLOv8PyQt&#xff0c;實現攝像頭或視頻的實時檢測 需要安裝 PySide6 和 ultralytics pip install PySide6 pip install ultralyticsfr…

基于docxtpl的模板生成Word

docxtpl是一個用于生成Microsoft Word文檔的模板引擎庫。它結合了docx模塊和Jinja2模板引擎&#xff0c;使用戶能夠使用Microsoft Word模板文件并在其中填充動態數據。這個庫提供了一種方便的方式來生成個性化的Word文檔&#xff0c;并支持條件語句、循環語句和變量等控制結構&…

如何在 Elasticsearch 中選擇精確 kNN 搜索和近似 kNN 搜索

作者&#xff1a;來自 Elastic Carlos Delgado kNN 是什么&#xff1f; 語義搜索&#xff08;semantic search&#xff09;是相關性排名的強大工具。 它使你不僅可以使用關鍵字&#xff0c;還可以考慮文檔和查詢的實際含義。 語義搜索基于向量搜索&#xff08;vector search&…

Angular Ivy:新渲染引擎的性能提升與優化

Angular Ivy是Angular 9及更高版本中引入的默認渲染引擎&#xff0c;它取代了以前的View Engine。Ivy的目標是提高Angular的性能、減少包大小和提高開發者的生產力。 1. AOT編譯的改進&#xff1a; 在Ivy中&#xff0c;Angular使用了更早的AOT&#xff08;Ahead-of-Time&…

在AnolisOS8.9系統安裝docker-compose

在AnolisOS8.9系統安裝docker-compose 下載docker-compose之前請先確保docker已經安裝完&#xff0c;教程可以參考 在阿里Anolis OS 8.9龍蜥操作系統安裝docker 下載最新版的docker-compose文件 sudo curl -L https://github.com/docker/compose/releases/download/v2.21.0…

大數據工具之HIVE-參數調優,調度亂碼(二)

一、調度亂碼 在利用HUE工具,搭建WORKFLOW流程的過程中,如果直接執行hivesql數據正常,不會出現亂碼現象,如果利用WORKFLOW搭建的流程,進行數據的拉取,會出現數據中文亂碼現象,這些亂碼主要是由于select 中的硬編碼中文導致出現的現象 具體現象如下: select case when …

百度 提前批 國際化廣告部 (深圳-機器學習/數據挖掘/自然語言處理工程師) 一面+二面面經

文章目錄 0、面試情況1、一面1.1、簡歷上的項目介紹了個遍1.2、dbscan原理1.3、為什么梯度的負方向就是損失函數下降最快的方向&#xff1f;1.4、bn原理&#xff0c;為什么bn能解決過擬合&#xff0c;1.5、auc原理&#xff0c;為什么ctr或你的廣告推薦里用auc指標&#xff1f;1…

TG5032CGN TCXO 超高穩定10pin端子型適用于汽車動力轉向控制器

TG5032CGN TCXO / VC-TCXO是一款應用廣泛的晶振&#xff0c;具有超高穩定性&#xff0c;CMOS輸出和使用晶體基振的削波正弦波輸出形式。且有低相位噪聲優勢&#xff0c;是溫補晶體振蕩器(TCXO)和壓控晶體振蕩器(VCXO)結合的產物&#xff0c;具有TCXO和VCXO的共同優點&#xff0…

后臺接口返回void但是response有設置合適的相關信息,前端調用接口解析Blob數據下載excel文件

1、pom.xml文件增加依賴&#xff1a; <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId></dependency> 2、接口代碼如下&#xff1a; /*** 企業列表--導出*/GetMapping(value "/downloadTenantL…

微信小程序上線必備:SSL證書申請以及安裝

一、認識ssl證書 1、ssl證書是什么&#xff1f; SSL證書&#xff0c;全稱Secure Socket Layer Certificate&#xff0c;是一種數字證書&#xff0c;它遵循SSL&#xff08;現在通常指TLS&#xff0c;Transport Layer Security&#xff09;協議標準&#xff0c;用于在客戶端&…

SpringCloud系列(26)--OpenFeign超時控制

前言&#xff1a;在上一章節中我們簡單的介紹了如何使用OprnFeign去調用微服務&#xff0c;因為消費側和服務側是兩個不同的微服務&#xff0c;這樣可能會出現超時的現象&#xff0c;例如服務側需要3秒處理任何才能返回結果&#xff0c;但消費側可能2秒就斷開連接了&#xff0c…

【深度學習】2.單層感知機

目標&#xff1a; 實現一個簡單的二分類模型的訓練過程&#xff0c;通過模擬數據集進行訓練和優化&#xff0c;訓練目標是使模型能夠根據輸入特征正確分類數據。 演示: 1.通過PyTorch生成了一個模擬的二分類數據集&#xff0c;包括特征矩陣data_x和對應的標簽數據data_y。標簽…