談談 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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...