欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

情況簡(jiǎn)述 

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

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

原因

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

被新的數(shù)組所替代,因?yàn)樵诓僮鞔韺?duì)象的時(shí)候需要有代理對(duì)象作為前提,所以失去了響應(yīng)式

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

就像對(duì)象的地址被替換,就不是原來的那個(gè)對(duì)象了

解決辦法

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

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

方法2:使用ref函數(shù)(ref可以創(chuàng)建任意數(shù)據(jù)類型,reactive只能創(chuàng)建對(duì)象或者數(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時(shí),我們發(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的值不會(huì)變,obj.a的值倒是一直在遞增。

我們都知道vue3是使用ES6的proxy特性來實(shí)現(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本身就是對(duì)對(duì)象進(jìn)行攔截,通過new Proxy的返回值,攔截obj對(duì)象,當(dāng)操作對(duì)象中的值時(shí),會(huì)觸發(fā)set或者get。

但是對(duì)于原始值(string、number這些),就需要在外部包裹一下變成一個(gè)對(duì)象,不然沒辦法使用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
? }
? // 使用一個(gè)對(duì)象包裹基本數(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把原始值包裝成一個(gè)對(duì)象,通過get value和set value方法來對(duì)原始值進(jìn)行訪問,這樣在訪問值的時(shí)候就必須攜帶.value了。

而對(duì)于對(duì)象而言,使用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)會(huì)破壞響應(yīng)式?

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

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

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

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

總結(jié)

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

相關(guān)文章

最新評(píng)論