alibaba / formily

📱🚀 🧩 Cross Device & High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3
https://formilyjs.org/
MIT License
11.36k stars 1.48k forks source link

[Bug Report] vue2+formily中出现的arrayMethods被代理导致vue2响应式数组原型被全量修改的问题 #3943

Closed TinaZbh closed 1 month ago

TinaZbh commented 1 year ago

Reproduction link

Edit on CodeSandbox

Steps to reproduce

这个栗子是个简化的复现栗子。 主要的流程就是: 1、一个proxy(Array)对象,被转成了vue2的observe数组 2、在转的过程中vue将改数组的原型指向了arrayMethods对象。 3、formily reactive将arrayMethods对象转为了proxy(arrayMethods)。 4、当我们修改改数组,往里面塞值,会导致所有vue2的observe数组,也就是原型是arrayMethods的数组都被修改了。用索引可以访问到原型arrayMethods上的数据

What is expected?

此时应该是undefined 不要代理arrayMethods对象。不影响所有数组原型arrayMethods的数据

What is actually happening?

返回了22 其他数组受到了影响(https://imgse.com/i/pPtCdoV

Package

@formily/reactive@2.2.13


janryWang commented 1 year ago

reactive 代理是 new Proxy ,它是不知道这个是不是被 vue 代理原型过的吧

TinaZbh commented 1 year ago

reactive 代理是 new Proxy ,它是不知道这个是不是被 vue 代理原型过的吧

@janryWang 是不是可以在formily reative内createObservable对象的时候,进行一个判断。因为arrayMethod对象本身其实不是一个数组。const arrayMethods = Object.create(Array.prototype)。只要不代理他,应该就不会出现影响到其他原型是它的数组了。辛苦大佬帮忙康康呢~

TinaZbh commented 1 year ago

reactive 代理是 new Proxy ,它是不知道这个是不是被 vue 代理原型过的吧

@janryWang 还有一个,就是我发现formily源码有这段“target[key] = newValue // use Reflect.set is too slow”。其实如果用Reflect.set, receiver就不会有问题。

janryWang commented 1 year ago

@TinaZbh trget[key] 这种写法肯定不能改,用 Reflect 巨慢,性能会成倍劣化

TinaZbh commented 1 year ago

@janryWang 哦好吧。不过感觉两个问题同时触发导致问题:1、监听proto属性修改,代理了原型对象。2、target[key]赋值的指向问题,赋值到了原型上,而不是目标对象上。

yiyunwan commented 1 month ago

已修复