Vue3響應式數據轉回原始普通對象的方法詳解
在 Vue(尤其 Vue3)里,把響應式數據(Proxy/Ref)轉回原始普通對象(用 toRaw),核心是:繞開響應式代理、避免不必要更新、兼容外部系統(tǒng)、提升性能、防止異常。
一、先搞懂:響應式 vs 原始數據
- 響應式數據:
reactive/ref生成的 Proxy 代理對象,自帶 getter/setter 攔截,用于依賴收集與視圖自動更新。 - 原始數據:被代理前的普通對象/數組/值,無 Proxy 包裹,修改不會觸發(fā) Vue 響應式更新。
二、為什么要轉成原始數據(核心場景)
1. 與第三方庫/原生 API 兼容(最常見)
很多庫/API 不認識 Vue 的 Proxy,直接傳會報錯、序列化異?;蛐袨楫惓?。
JSON 序列化/存儲:JSON.stringify 對 Proxy 可能輸出異常(含內部元數據),必須轉原始
const user = reactive({ name: '張三' })
// ? 可能輸出帶 __v_isReactive 等內部字段
localStorage.setItem('user', JSON.stringify(user))
// ? 正確:轉原始再序列化
localStorage.setItem('user', JSON.stringify(toRaw(user)))圖表/地圖/Three.js/D3 等外部庫:它們期望純 JS 對象,傳 Proxy 會報錯或性能極差
import * as d3 from 'd3'
const data = reactive([1,2,3])
d3.select('svg').selectAll('rect').data(toRaw(data)) // ? 必須原始
Lodash/工具函數:深層遍歷/克隆時,Proxy 會觸發(fā)額外依賴追蹤,導致性能問題或死循環(huán)
2. 性能優(yōu)化:批量/大量數據操作
對超大數組/對象做循環(huán)、排序、過濾、批量修改時:
- 直接操作響應式對象:每一次修改都會觸發(fā)依賴收集與可能的更新,性能極低
- 轉原始后操作:無 Proxy 開銷、不觸發(fā)更新,最后再同步回響應式對象
const list = reactive(Array(10000).fill(0)) const rawList = toRaw(list) // 批量處理:只操作原始,不觸發(fā)更新 for (let i = 0; i < rawList.length; i++) rawList[i] = i * 2 // 最后同步一次(可選) list.splice(0, list.length, ...rawList)
3. 避免無限遞歸/循環(huán)更新
場景1:對象自引用(如樹、鏈表、狀態(tài)里存自身)
const state = reactive({ data: null })
state.data = toRaw(state) // ? 存原始,避免 Proxy 遞歸監(jiān)聽自己
場景2:監(jiān)聽/計算屬性里修改自身,容易死循環(huán);用原始數據做中間計算
4. 只讀不觸發(fā)響應式(調試/日志/臨時計算)
打印/調試時,不想觸發(fā)依賴追蹤,也不想看到 Proxy(Object),想看真實數據
const form = reactive({ name: '李四' })
console.log(toRaw(form)) // { name: '李四' },干凈的原始對象
臨時計算、判斷、緩存,不需要視圖更新,用原始更安全高效
5. 提交后端/接口請求
后端只認普通 JSON,不認 Proxy;雖然多數 axios/fetch 能自動處理,但轉原始更穩(wěn)妥、避免隱式問題
const params = reactive({ id: 1, name: 'xxx' })
axios.post('/api', toRaw(params)) // ? 更干凈
6. 規(guī)避響應式副作用
- 某些場景下,你明確不希望修改觸發(fā)視圖更新(如臨時草稿、后臺計算),用原始數據操作
三、怎么轉:Vue3 核心 API
import { reactive, ref, toRaw } from 'vue'
// 1. reactive 對象 → 原始
const user = reactive({ name: '張三' })
const rawUser = toRaw(user) // 普通對象
// 2. ref 對象 → 原始(先取 .value)
const count = ref(0)
const rawCount = toRaw(count.value) // 原始值
// 3. 只讀/淺響應 → 也能轉
const ro = readonly(user)
toRaw(ro) === rawUser // true
四、重要注意
toRaw只解最外層:嵌套對象如果也是響應式,依然是 Proxy,需要遞歸處理- 修改原始會同步到響應式:原始與響應式指向同一塊內存,改原始會改數據,但不觸發(fā)更新
- 不要替換響應式對象:
user = rawUser會丟失響應式,應修改屬性或用Object.assign - Vue2 不同:Vue2 用
Object.defineProperty,無toRaw,一般用JSON.parse(JSON.stringify(obj))深拷貝轉普通對象
五、一句話總結
需要轉原始數據,本質是:當你要和 Vue 響應式系統(tǒng)“脫鉤”時——和外部交互、大量計算、避免遞歸、只看不更、性能敏感,就用 toRaw 拿原始數據。
以上就是Vue3響應式數據轉回原始普通對象的方法詳解的詳細內容,更多關于Vue3響應式數據轉回原始普通對象的資料請關注腳本之家其它相關文章!
相關文章
Vue 3 中使用路由參數跳轉時 watch 觸發(fā)重復請求問題解決
Vue3中watch(route.query.id)可能因跨頁參數變化重復觸發(fā)請求,需通過路由name判斷當前頁面,避免誤操作,route.query是響應式,setup不重執(zhí)行,watch需手動處理上下文,本文給大家介紹Vue 3 中使用路由參數跳轉時 watch 觸發(fā)重復請求問題解決,感興趣的朋友一起看看吧2025-07-07
vue在mounted中window.onresize不生效問題及解決
這篇文章主要介紹了vue中在mounted中window.onresize不生效問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04
基于 vue-skeleton-webpack-plugin 的骨架屏實戰(zhàn)
這篇文章主要介紹了基于 vue-skeleton-webpack-plugin 的骨架屏實戰(zhàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-08-08

