談談 Vue toRef 和 reactive

来源:https://www.cnblogs.com/Himmelbleu/archive/2023/03/19/17229273.html
-Advertisement-
Play Games

reactive reactive 創建一個深層的對象的響應式代理,即對象根屬性以及嵌套對象的屬性都是響應式的。如果使用 ES6 結構賦值,就會使得這個對象的響應式代理第一層(根屬性)屬性失去響應式,但其嵌套下的對象屬性還是響應式的。 shallowReactive 會創建淺層的對象的響應式代理,只 ...


reactive

reactive 創建一個深層的對象的響應式代理,即對象根屬性以及嵌套對象的屬性都是響應式的。如果使用 ES6 結構賦值,就會使得這個對象的響應式代理第一層(根屬性)屬性失去響應式,但其嵌套下的對象屬性還是響應式的。

shallowReactive 會創建淺層的對象的響應式代理,只有第一層(根屬性)屬性有響應式,其嵌套對象的屬性不是響應式。

// 解構賦值
const { foo, bar } = { ...reactive({ foo: 1, bar: { val: 1 } }) };
<div>foo: {{ foo }}</div>
<button @click="foo++">Change foo</button>
<div>bar val: {{ bar.val }}</div>
<button @click="bar.val++">Click bar val</button>

圖1 - reactive 被解構賦值失去響應式

如上圖所示,foo 只有在 bar.val 響應式更新之後才更新。被解構賦值之後,foo 是根屬性,失去了響應式;bar 是嵌套對象,其屬性還有響應式。

toRef

toRef基於響應式對象上的一個屬性,創建一個對應的 ref。這裡有非常重要的註意點,“響應式”、“對象”。toRef 操作的是一個響應式數據,且數據類型是對象,而不是一個普通對象,即便控制台不報錯,也會失去它的意義。

const obj = {
  foo: {
    bar: 1
  }
};

const state = toRef(obj, "foo");

function change() {
  state.value.bar++;
  console.log(state.value.bar, obj.foo.bar);
}
<div>obj: {{ obj.foo.bar }}</div>
<div>foo: {{ state.bar }}</div>
<button @click="change">Change foo bar</button>

如下圖所示,頁面不發生更新:

圖2 - toRef 得到的 Ref 數據不是響應式的

state 確實是 Ref 類型:

圖3- toRef 得到的普通對象屬性的類型是 Ref

也就是說,toRef 操作的數據不能是普通對象的屬性。

toRef 作用是什麼?

延續響應式能力

下麵是官方文檔給出的示例,左看右看、上看下看都沒看出個啥特別的。謎語人吧這是?

const state = reactive({
  foo: 1,
  bar: 2
})

const fooRef = toRef(state, 'foo')

// 更改該 ref 會更新源屬性
fooRef.value++
console.log(state.foo) // 2

// 更改源屬性也會更新該 ref
state.foo++
console.log(fooRef.value) // 3

❓那麼 toRef 有什麼用呢?前面說到 reactive 被解構賦值之後第一層(根屬性)失去了響應式,而 toRef 可以讓其繼續保持響應式。

toRef 當作 ref 函數創建一個響應式數據不是響應式的,頁面不更新,前面圖2 中已經說明瞭。toRef延續響應式能力,不是創建響應式數據

對第一節中的例子進行修改:

// 在 reactive 中包裹了 toRefs
const { foo, bar } = { ...toRefs(reactive({ foo: 1, bar: { val: 1 } })) };

圖4 - toRefs 包裹之後延續了 reactive 被解構賦值的響應式能力

圖4 與 圖1 進行對比,foo 確確實實是響應式的,頁面也發生了變化。不再因為 bar.val 更新而更新。

toRef 與 toRefs 的區別就是多了一個 s,即批量延續 reactive 的響應式能力。

轉換 prop 為 Ref 類型

官方文檔中有提到關於 prop 與 toRef 結合使用的案例,說非常有用。有些函數需要的參數類型就是 Ref,比如 useRefHistory,就需要傳遞 Ref 類型的數據:

image

組件 prop 不是一個 Ref 類型的數據:

console.log(isRef(props.foo)); // => false

因此,用 toRef 轉換類型,與原始數據保持同步:

useRefHistory(toRef(props, "foo"));

總結

toRef 是延續響應式,不是創建響應式數據,不能等同於 ref 函數。為何是延續響應式,需要查閱源碼方可知曉。本博客只是從表現中得到的結論,沒有從原理上進行總結,屬於經驗之談。

toRef 只能基於響應式數據進行操作,對普通的對象進行操作得到的數據不是響應式的。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • #[EF Core] EF Core Code-First 移除外鍵 —— 重寫SQL生成器 使用EF Core時最煩的就是生成的某些 SQL 其實並不是你想要的結果,例如外鍵約束等等。 一個最簡單的例子就是,因為EF Core會根據導航屬性生成外鍵約束等原因,導致很多開發者拋棄了更易維護的Code ...
  • 1、OpenGL有多個標準,如Open ES是為了移動設備,目前通常使用OpenTK.Graphics.OpenGL4對應OpenGL4.x版本,2010年是OpenGL分割領,之前是3版本,之後都是4版本,目前最新4.6,更新頻率不高 2、OpenGL的著色語言GLSL,對應的文件擴展名.vert ...
  • 最近寫了一個demo:demo的github地址 一. 簡單介紹 1. Server端 它是一個WebApi服務,把它當成一個黑盒就行了。 2. MiddleServer端 是重點,它是一個WebApi服務,包含一個GetValues介面和一個Query2介面。 Query2介面是一個簡單的介面。 ...
  • Watchtower 是一個用於自動更新 Docker 容器的工具。它可以監視 Docker Hub 或私有倉庫中的鏡像,併在發現新的鏡像版本時自動更新容器。 ...
  • (文章目錄) 01、首先配置文件地址改了 地址為 ` /etc/NetworkManager/system-connections/網卡名 ` 網卡名可以使用 ip a查看,紅框中就是網卡名 網卡名 ls命令可以看到有以下配置文件 ` es160.nmconnection ` vi編輯 ` [con ...
  • 一、共用記憶體是什麼 在Linux系統中,共用記憶體是一種IPC(進程間通信)方式,它可以讓多個進程在物理記憶體中共用一段記憶體區域。 這種共用記憶體區域被映射到多個進程的虛擬地址空間中,使得多個進程可以直接訪問同一段物理記憶體區域中的數據,從而實現進程間的高速數據交換和通信。 二、共用記憶體的原理 共用記憶體基於 ...
  • 前騰訊工程師,經歷過大廠,也經歷過創業! 我已奔四,但我還在持續學習,持續成長! 我非常樂意把我的經驗和心得分享給你! 我是阿銘,關註我,和我一起成長為技術大牛! ↓↓↓↓↓ 關於DevOps這個概念,可能100個人能給出100個說法,這是因為每個人所接觸到的環境有所差異,不同的公司要解決的問題自然 ...
  • 案例現象 這天,監控系統發來一條告警消息,內容說某台伺服器根目錄磁碟占用空間達到閾值,超過百分之八十了 登上伺服器,df -Th 看一下,發現磁碟空間確實不夠用了 進入到根目錄,然後 du -sh * 可以看到,var 目錄下的磁碟空間已經占用了 75G 既然如此,刪除 var 目錄下一些占空間較大 ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...