vue3中获取proxy原始对象的问题

2020-11-25  本文已影响0人  AaronZ_dd7f

项目中遇到如下问题

  1. 在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)
  1. 在组件中,需要用到passengers的数据作为复选框的值,部分代码如下
const passengersChecked = ref(new Set(unref(passengers)))
  1. 在页面操作后,用户提交,开始组装报文
const passengersCheckedValue = toRaw(unref(passengersChecked))
  1. 发现passengersCheckedValue<Set>里面都是响应式对象
console.log(passengersCheckedValue) // Set(4) {Proxy, Proxy, Proxy, Proxy}

原因

  1. Set 构造函数 会访问数组Symbol(Symbol.iterator)、length属性和每一个key,只要访问了就会触发代理的get陷阱,get陷阱会对访问到的值继续做响应化处理
get陷阱会对访问到的属性的值继续响应化
  1. 生成的Set中的子元素就是响应化后的对象,而不再原来的Object。既Set(4) {Proxy, Proxy, Proxy, Proxy}

  2. 然后在对Set(4) {Proxy, Proxy, Proxy, Proxy}进行响应式化。此时的target就是Set(4) {Proxy, Proxy, Proxy, Proxy}

  3. 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
上一篇下一篇

猜你喜欢

热点阅读