項(xiàng)目中遇到如下問(wèn)題
- 在usePassengers先將數(shù)組arr通過(guò)ref響應(yīng)式化
// 用戶的數(shù)據(jù)
const data = [
{ id: 1, name: 'a' },
{ id: 2, name: 'b' },
{ id: 3, name: 'c' },
{ id: 4, name: 'd' }
]
// 此處做響應(yīng)化
const passengers = ref(data)
- 在組件中黍聂,需要用到passengers的數(shù)據(jù)作為復(fù)選框的值灌砖,部分代碼如下
const passengersChecked = ref(new Set(unref(passengers)))
- 在頁(yè)面操作后花嘶,用戶提交辱姨,開(kāi)始組裝報(bào)文
const passengersCheckedValue = toRaw(unref(passengersChecked))
- 發(fā)現(xiàn)passengersCheckedValue<Set>里面都是響應(yīng)式對(duì)象
console.log(passengersCheckedValue) // Set(4) {Proxy, Proxy, Proxy, Proxy}
原因
- Set 構(gòu)造函數(shù) 會(huì)訪問(wèn)數(shù)組Symbol(Symbol.iterator)、length屬性和每一個(gè)key振诬,只要訪問(wèn)了就會(huì)觸發(fā)代理的get陷阱蹭睡,get陷阱會(huì)對(duì)訪問(wèn)到的值繼續(xù)做響應(yīng)化處理
生成的Set中的子元素就是響應(yīng)化后的對(duì)象,而不再原來(lái)的Object赶么。既Set(4) {Proxy, Proxy, Proxy, Proxy}
然后在對(duì)Set(4) {Proxy, Proxy, Proxy, Proxy}進(jìn)行響應(yīng)式化肩豁。此時(shí)的target就是Set(4) {Proxy, Proxy, Proxy, Proxy}
toRaw 只是返回響應(yīng)式對(duì)象的ReactiveFlags.RAW(__v_raw)屬性,為target辫呻。
解決方案
// 1. 在生成Set的時(shí)候就獲取去響應(yīng)化后的值
const passengersChecked = ref(new Set(toRaw(unref(passengers))))
// 2. 使用shallowRef清钥,只跟蹤自己的 .value 更改,但不會(huì)使其值成為響應(yīng)式的放闺。
const passengers = shallowRef(data)
如下的這些操作也會(huì)造成對(duì)數(shù)組屬性的訪問(wèn)祟昭,從而觸發(fā)代理的get陷阱
const passengersChecked = [...passengers]
// 同 new Set(passengers)
// 屬性訪問(wèn)順序 Symbol(Symbol.iterator) length 0 length 1 length 2 length 3
const passengersChecked = Object.entries(passengers)
// 屬性訪問(wèn)順序 0 1 2 3
const passengersChecked = Object.values(passengers)
// 屬性訪問(wèn)順序 0 1 2 3