亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

vue3中遇到reactive響應(yīng)式失效的問題記錄

 更新時間:2023年06月06日 10:24:50   作者:柑橘烏云_  
這篇文章主要介紹了vue3中遇到reactive響應(yīng)式失效的問題記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

vue3中reactive響應(yīng)式失效

情況簡述 

初始化了一個reactive的空數(shù)組,之后調(diào)用接口,將接口返回的數(shù)據(jù)賦值給這個reactive,此時發(fā)現(xiàn)頁面數(shù)據(jù)并沒有更新。(場景:ele-table的dataList)

const dataList = reactive([]);
const load = async () => {
? const res = await 接口函數(shù)(); //假設(shè)請求接口返回的數(shù)據(jù)
? // 方法1 失敗,直接賦值丟失了響應(yīng)性
? // dataList = res;
? // 方法2 這樣也是失敗
? // dataList.concat(res);
};

原因

直接把一個新的數(shù)組賦值給dataList,導(dǎo)致reactive聲明的響應(yīng)式對象由dataList代理

被新的數(shù)組所替代,因為在操作代理對象的時候需要有代理對象作為前提,所以失去了響應(yīng)式

在vue3中不管是對象還是數(shù)組都不能直接將整個數(shù)據(jù)進行賦值,這樣會造成reactive定義的響應(yīng)式失效

就像對象的地址被替換,就不是原來的那個對象了

解決辦法

方法1:創(chuàng)建一個響應(yīng)式對象,對象的屬性是數(shù)組

let datalist = reactive({
? list: [],
})
let arr = [1,2,3]
datalist.list = arr

方法2:使用ref函數(shù)(ref可以創(chuàng)建任意數(shù)據(jù)類型,reactive只能創(chuàng)建對象或者數(shù)組)

const datalist = ref([])
datalist.value = [1, 2, 3]?

方法3:數(shù)組的push

let datalist = reactive([])
let arr = [1, 2, 3]
arr.forEach((item) => {?
?datalist.push(item)
})?

let datalist = reactive([])
let arr = [1, 2, 3]
datalist.push(...arr)

vue3解構(gòu)響應(yīng)式失效解析

在使用vue3時,我們發(fā)現(xiàn)不能使用解構(gòu)來處理響應(yīng)式數(shù)據(jù),今天我們來看看究竟是為什么。

在vue3中解構(gòu)響應(yīng)式數(shù)據(jù)

<div>{{counter}}</div>
<div>{{obj.value}}</div>
const reactiveObj = reactive({
? counter: 0,
? obj: {
? ? value: 1
? }
});
setInterval(() => {
? reactiveObj.counter++;
? reactiveObj.obj.value++;
}, 1000);
const { counter, obj } = reactiveObj;
return {
? counter,
? obj
};

在頁面上可以看到,counter的值不會變,obj.a的值倒是一直在遞增。

我們都知道vue3是使用ES6的proxy特性來實現(xiàn)響應(yīng)式的,先來回顧一下proxy。

const obj = {
? ? value: 1
}
const proxy = new Proxy(obj, {
? ? get: function(target, key) {
? ? ? ? return Reflect.get(...arguments);
? ? },
? ? set: function(target, key, value) {
? ? ? ? return Reflect.set(...arguments)
? ? }
})
proxy.value++;
console.log(proxy.value); ? // 2

proxy本身就是對對象進行攔截,通過new Proxy的返回值,攔截obj對象,當操作對象中的值時,會觸發(fā)set或者get。

但是對于原始值(string、number這些),就需要在外部包裹一下變成一個對象,不然沒辦法使用new Proxy去攔截。

我們來看看vue3是如何處理的。

在vue3中,使用ref來為基本數(shù)據(jù)類型添加響應(yīng)式。

export function ref(value?: unknown) {
? return createRef(value, false)
}
function createRef(rawValue: unknown, shallow: boolean) {
? if (isRef(rawValue)) {
? ? return rawValue
? }
? // 使用一個對象包裹基本數(shù)據(jù)類型數(shù)據(jù)
? return new RefImpl(rawValue, shallow)
}
class RefImpl<T> {
? private _value: T
? private _rawValue: T
? public dep?: Dep = undefined
? public readonly __v_isRef = true
? constructor(value: T, public readonly __v_isShallow: boolean) {
? ? this._rawValue = __v_isShallow ? value : toRaw(value)
? ? this._value = __v_isShallow ? value : toReactive(value)
? }
? get value() {
? ? trackRefValue(this)
? ? return this._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)
? ? ? triggerRefValue(this, newVal)
? ? }
? }
}

從上面的代碼可以發(fā)現(xiàn),vue3把原始值包裝成一個對象,通過get value和set value方法來對原始值進行訪問,這樣在訪問值的時候就必須攜帶.value了。

而對于對象而言,使用ref的話內(nèi)部還是調(diào)用reactive。

export const toReactive = <T extends unknown>(value: T): T =>
? isObject(value) ? reactive(value) : value
export function reactive(target: object) {
? if (isReadonly(target)) {
? ? return target
? }
? return createReactiveObject(
? ? target,
? ? false,
? ? mutableHandlers,
? ? mutableCollectionHandlers,
? ? reactiveMap
? )
}

但是還是需要通過.value去訪問內(nèi)部的響應(yīng)式數(shù)據(jù).

let reactiveObj = ref({
? counter: 0,
? obj: {
? ? a: 1
? }
});
console.log(reactiveObj.value.obj.a);

為什么解構(gòu)會破壞響應(yīng)式?

解構(gòu)賦值,區(qū)分基本數(shù)據(jù)類型和引用類型的賦值,原始類型的賦值相當于按值傳遞,引用類型的值就相當于按引用傳遞。

const obj = {
? value: 1,
? obj1: {
? ? value: 1
? }
}
const val = obj.value;
const obj1 = obj.obj1;

上方的val雖然是obj.value的值,但是當訪問val時,已經(jīng)繞過了obj對象的get方法,也就是本文討論的失去響應(yīng)式。

而obj1在解構(gòu)出來的值是按引用傳遞的,內(nèi)部的指針依然指向obj.obj1,所以去訪問其中的內(nèi)容并不會失去響應(yīng)式。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論