Vue3中reactive丟失響應(yīng)式問題詳解
問題描述:
使用 reactive 定義的對象,重新賦值后失去了響應(yīng)式,改變值視圖不會發(fā)生變化。
測試代碼:
<template> <div> <p>{{ title }}</p> <ul> <li v-for="(item, index) in tableData" :key="index">{{ item }}</li> </ul> </div> </template> <script setup> import { ref, reactive, onMounted } from 'vue' const title = ref('我是標(biāo)題') let tableData = reactive([1, 2, 3]) onMounted(() => { title.value = '我是段落', tableData = [1, 1, 1] console.log("title=", title) console.log("tableData=", tableData) }) </script>
輸出結(jié)果:
從上述測試代碼中,ref 定義的對象有響應(yīng)式,而 reactive 定義的對象失去了響應(yīng)式,這是什么原因呢?官網(wǎng)中寫到:
如果將一個對象賦值給 ref ,那么這個對象將通過 reactive() 轉(zhuǎn)為具有深層次響應(yīng)式的對象。
那么,為什么 ref 調(diào)用 reactive 處理對象重新賦值后,不會丟失響應(yīng)式,但 reactive 卻丟失了呢?
第一步:當(dāng)我們修改 xxx.value 值的時候,setter 調(diào)用了 toReactive 方法
class RefImpl { constructor(value, __v_isShallow) { this.__v_isShallow = __v_isShallow; this.dep = undefined; this.__v_isRef = true; this._rawValue = __v_isShallow ? value : toRaw(value); this._value = __v_isShallow ? value : toReactive(value); } get value() { trackRefValue(this); return this._value; // get方法返回的是_value的值 } set value(newVal) { newVal = this.__v_isShallow ? newVal : toRaw(newVal); if (hasChanged(newVal, this._rawValue)) { this._rawValue = newVal; this._value = this.__v_isShallow ? newVal : toReactive(newVal); // set方法調(diào)用 toReactive 方法 triggerRefValue(this, newVal); } } }
第二步:toReactive 方法判斷是否是對象,是的話就調(diào)用 reactive 方法
const toReactive = (value) => isObject(value) ? reactive(value) : value;
第三步:reactive 方法,先判斷數(shù)據(jù)是否是“只讀”的,不是就返回 createReactiveObject() 方法處理后的數(shù)據(jù)(createReactiveObject 方法將對象通過 proxy 處理為響應(yīng)式對象)
function reactive(target) { // if trying to observe a readonly proxy, return the readonly version. if (isReadonly(target)) { return target; } return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap); }
結(jié)論:
ref 定義數(shù)據(jù)(包括對象)時,都會變成 RefImpl(Ref 引用對象) 類的實(shí)例,無論是修改還是重新賦值都會調(diào)用 setter,都會經(jīng)過 reactive 方法處理為響應(yīng)式對象。
但是 reactive 定義數(shù)據(jù)(必須是對象),是直接調(diào)用 reactive 方法處理成響應(yīng)式對象。如果重新賦值,就會丟失原來響應(yīng)式對象的引用地址,變成一個新的引用地址,這個新的引用地址指向的對象是沒有經(jīng)過 reactive 方法處理的,所以是一個普通對象,而不是響應(yīng)式對象。
如何正確使用 reactive 呢?
使用 reactive 定義數(shù)據(jù)時,使用對象包含鍵值對的形式,那么就會避免重新賦值的問題。那么,修改測試代碼為:
<template> <div> <p>{{ title }}</p> <ul> <li v-for="(item, index) in obj.tableData" :key="index">{{ item }}</li> </ul> </div> </template> <script setup> import { ref, reactive, onMounted } from 'vue' const title = ref('我是標(biāo)題') let obj = reactive({ tableData: [1, 2, 3] }) onMounted(() => { title.value = '我是段落', obj.tableData = [1, 1, 1] }) </script>
總結(jié)
到此這篇關(guān)于Vue3中reactive丟失響應(yīng)式問題的文章就介紹到這了,更多相關(guān)Vue3 reactive丟失響應(yīng)式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue+elementUI實(shí)現(xiàn)當(dāng)渲染文本超出一定字?jǐn)?shù)時顯示省略號
這篇文章主要介紹了vue+elementUI實(shí)現(xiàn)當(dāng)渲染文本超出一定字?jǐn)?shù)時顯示省略號,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10在vue中解決提示警告 for循環(huán)報(bào)錯的方法
今天小編就為大家分享一篇在vue中解決提示警告 for循環(huán)報(bào)錯的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09Vue的事件響應(yīng)式進(jìn)度條組件實(shí)例詳解
這篇文章主要介紹了Vue的事件響應(yīng)式進(jìn)度條組件的實(shí)例代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2018-02-02element-ui?table使用type='selection'復(fù)選框全禁用(全選禁用)詳解
element-ui中的table的多選很好用,但是如果其中某一項(xiàng)禁止選擇,該怎樣操作呢,下面這篇文章主要給大家介紹了關(guān)于element-ui?table使用type='selection'復(fù)選框全禁用(全選禁用)的相關(guān)資料,需要的朋友可以參考下2023-01-01