詳細講一講vue3下會造成響應式丟失的情況
題引:
在我們從vue2過渡到vue3的時候,對于數(shù)據(jù)響應式的變化其實是懵懵懂懂的。從以往直接在data函數(shù)里面定義變量到每一次都要使用ref/reactive時,是有些不適應的。但問題不大,畢竟在大前端時代中,如果不及時跟上時代的步伐,不僅技術沒跟上,面試還容易被卡。所以今天來聊聊在使用vue3開發(fā)時對于數(shù)據(jù)響應式的理解。
vue3的響應式是基于 proxy
從vue2的 Object.defineProperty
到vue3的 proxy
可謂是一個質(zhì)的飛躍。vue2的響應式是需要遞歸+遍歷每一個對象的屬性進行數(shù)據(jù)劫持,而在vue3中只需要對對象層進行監(jiān)聽即可。好了話不多說,開始講解一些常見的響應式問題。
ref和reactive之間的關系
如果我們用ref定義基本類型時,實際上還是使用 Object.defineProperty
進行數(shù)據(jù)劫持監(jiān)聽。但如果是定義引用類型時,底層代碼上是借用 reactive
函數(shù)進行數(shù)據(jù)劫持的。因此ref和reactive關系是緊湊的。通過源碼的我們是可以確認的。
我們可以看到,this_value = useDirectValue ? newVal : toReactive(newVal) 是進行了判斷,而 useDirectValue 是進行判斷是否是淺層的、僅可讀的數(shù)據(jù)。 那么如果我們傳入的是一個對象,那么就會進入 toReactive(newVal) 這一步。 toReactive
函數(shù)就是進行reactive定義的函數(shù)入口。
reactive定義的變量重新賦值會失去響應式,而ref不會
我們一開始接觸vue3的時候,會對這個問題十分的不解,只是知道有這個問題而不知其根,今天就來講講這個問題。
import {ref,reactive} from 'vue'; let test = {age:2}; let obj = reactive({age:1}) let obj1 = ref({age:1}) obj = test; obj1.value = test;
通過reactive()包含的對象是進行了內(nèi)部的proxy代理,因此具有響應式。但是像test這個對象,它是沒有進行數(shù)據(jù)劫持的,而對象賦值的時候?qū)嶋H上是引用地址賦值。那么obj這個對象變成了一個沒有數(shù)據(jù)劫持的引用地址,那么它也就失去了響應式。但是obj1重新賦值時會保留自身的響應式。其實很簡單,跟上圖的代碼是有關的。細心的人會發(fā)現(xiàn),在 set
函數(shù)里面有這么一段代碼。
是的,在我們對ref定義的變量重新賦值時會進入 set
函數(shù),且重新賦值的是一個對象的話,那么它會再次進入 toReactive
函數(shù)進行數(shù)據(jù)劫持,這就是為什么ref定義的變量重新賦值對象時依舊保留響應式的根本原因。
解構響應式對象會造成響應式丟失
通過上面我都知道,不管是ref還是reactive定義的對象變量,都會經(jīng)過 reactive
函數(shù)來進行proxy代理。但是即使是對象,也會出現(xiàn)響應式丟失的情況。
<script setup> import {reactive,onMounted} from 'vue'; let obj = {a:18,aa:{age:18},aaa:{friend:{age:18}} } let rect = reactive(obj); let {a,aa,aaa} = rect; onMounted(()=>{setTimeout(()=>{a = 2;aa.age = 2;aaa.friend.age = 2;},2000) }) </script> <template><div>{{a}}</div><div>{{aa.age}}</div><div>{{aaa.friend.age}}</div> </template>
上面的運行結(jié)果就是,a變量沒有響應式,aa和aaa都是響應式。這是因為在解構賦值中,如果是原始類型的話是按照值傳遞,如果是引用類型的話是按照引用地址傳遞。除此之外 reactive()
定義的變量中 get函數(shù) 有這樣的一個處理
a = rect.a; //rect.a是一個基本類型,所以是直接賦值 aa = rect.aa; //rect.aa是一個引用類型,在內(nèi)部處理時觸發(fā)條件判斷,且非可讀對象即從Map數(shù)據(jù)結(jié)構中返回已經(jīng)代理的響應式對象 aaa = rect.aaa //跟rect.aa一個道理
因此以后對響應式對象進行解構時,記住以上的內(nèi)部判斷邏輯就可以拿捏它們了(#.#)。當然,對vuex或者pinia的取值也是這個道理,也就是為什么需要借助 computed()
來實現(xiàn)響應式了。因此 computed()
能返回響應式。
最后
到此這篇關于vue3下會造成響應式丟失的情況的文章就介紹到這了,更多相關vue3造成響應式丟失的情況內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue項目登錄模塊滑塊拼圖驗證功能實現(xiàn)代碼(純前端)
滑塊驗證作為一種反機器人的工具,也會不斷發(fā)展和演進,以適應不斷變化的威脅,這篇文章主要給大家介紹了vue項目登錄模塊滑塊拼圖驗證功能實現(xiàn)的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-07-07解決vue項目中type=”file“ change事件只執(zhí)行一次的問題
這篇文章主要介紹了vue項目中解決type=”file“ change事件只執(zhí)行一次的問題,本文給大家介紹的非常詳細,需要的朋友可以參考下2018-05-05Vite中使用Ant?Design?Vue3.x框架教程示例
這篇文章主要為大家介紹了Vite中使用Ant?Design?Vue3.x框架教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06vue實現(xiàn)element表格里表頭信息提示功能(推薦)
小編最近接了這樣一個需求,需要在element表格操作一欄添加提示功能,下面小編給大家?guī)砹嘶趘ue實現(xiàn)element表格里表頭信息提示功能,需要的朋友參考下吧2019-11-11