vue3中获取proxy原始对象的问题
2020-11-25 本文已影响0人
AaronZ_dd7f
项目中遇到如下问题
- 在usePassengers先将数组arr通过ref响应式化
// 用户的数据
const data = [
{ id: 1, name: 'a' },
{ id: 2, name: 'b' },
{ id: 3, name: 'c' },
{ id: 4, name: 'd' }
]
// 此处做响应化
const passengers = ref(data)
- 在组件中,需要用到passengers的数据作为复选框的值,部分代码如下
const passengersChecked = ref(new Set(unref(passengers)))
- 在页面操作后,用户提交,开始组装报文
const passengersCheckedValue = toRaw(unref(passengersChecked))
- 发现passengersCheckedValue<Set>里面都是响应式对象
console.log(passengersCheckedValue) // Set(4) {Proxy, Proxy, Proxy, Proxy}
原因
- Set 构造函数 会访问数组Symbol(Symbol.iterator)、length属性和每一个key,只要访问了就会触发代理的get陷阱,get陷阱会对访问到的值继续做响应化处理
get陷阱会对访问到的属性的值继续响应化
-
生成的Set中的子元素就是响应化后的对象,而不再原来的Object。既Set(4) {Proxy, Proxy, Proxy, Proxy}
-
然后在对Set(4) {Proxy, Proxy, Proxy, Proxy}进行响应式化。此时的target就是Set(4) {Proxy, Proxy, Proxy, Proxy}
-
toRaw 只是返回响应式对象的ReactiveFlags.RAW(__v_raw)属性,为target。
源码中的toRaw
解决方案
// 1. 在生成Set的时候就获取去响应化后的值
const passengersChecked = ref(new Set(toRaw(unref(passengers))))
// 2. 使用shallowRef,只跟踪自己的 .value 更改,但不会使其值成为响应式的。
const passengers = shallowRef(data)
如下的这些操作也会造成对数组属性的访问,从而触发代理的get陷阱
const passengersChecked = [...passengers]
// 同 new Set(passengers)
// 属性访问顺序 Symbol(Symbol.iterator) length 0 length 1 length 2 length 3
const passengersChecked = Object.entries(passengers)
// 属性访问顺序 0 1 2 3
const passengersChecked = Object.values(passengers)
// 属性访问顺序 0 1 2 3