Vue 无法检测对象和数组内部的修改是 因为实现不了么 还是性能问题。

2020-04-17 00:45:27 +08:00
 xcstream
1511 次点击
所在节点    问与答
8 条回复
kevin1
2020-04-17 00:47:48 +08:00
前排等答案。
rabbbit
2020-04-17 00:49:28 +08:00
renmu
2020-04-17 01:39:47 +08:00
因为是用 es5 的 defineproperty ()来实现的,天生有缺陷所以实现不了。
它是是在每个 object 创建的时候为每个添加了 getter 和 setter,之后对 object 直接修改,自然无法进行追踪。
数组的话是因为只有 push,slice 等几个有些的函数才能触发 setter
murmur
2020-04-17 08:48:24 +08:00
没有的,检测不了你可以用$set 方法(在对象中添加数据,修改特定下标)强制触发 diff,vue 基本不依赖 react 那种不可变对象的设计
Elephant696
2020-04-17 16:18:50 +08:00
vue2 是用 Object.defineProperty 来进行数据劫持的。这个方法本身就不支持劫持数组,对对象也仅仅是对对象的属性进行劫持。所以 vue 内部重写了数组的那几个方法。对对象也是做了遍历去劫持每个属性。所以可以说是因为实现不了才导致了性能问题。
当然 vue3 就没这个问题了。期待 ing
xcstream
2020-04-17 16:54:46 +08:00
懂了 vue3 可以解决这个问题
Sapp
2020-08-12 19:51:03 +08:00
如果我没理解错误的话,楼上的都说的不完全对,包括 vue 文档,这是一个很复杂也很令人费解的问题,我不清楚 vue 为什么要这么设计,事实上 Object. defineProperty 是可以做到追踪数组变化的,就算在 vue 里,vue 也实现了对数组的一部分操作,比如
data() {

}
Sapp
2020-08-12 19:59:28 +08:00
接楼上
比如

data() {
return {
list: [{name: '小明'}]
}
}

methods: {
hanlderClick() {
this.list[0].name ='小刚'
}
}

你可以尝试一下,vue 在页面是会追踪这个变化的,翻一下 vue 源码你就知道,vue 在对于数组的处理走了一个遍历,当是对象的时候劫持一下这个对象,是其他类型则不处理,这也是我很费解的地方所在,按照 vue 作者的说法不处理数组是因为性能问题,可是又为什么要对对象进行处理呢? 既然对对象进行处理,顺带把其他类型也处理了不可以么? 另一个很费解的地方就是 vue 在文档里并没有很深入的提到这个问题,只是说了 Object.defineProperty 不能劫持数组本身,但是这并不代表就不能实现解除数组元素(事实上 vue 也确实劫持了数组里的对象元素)

https://codesandbox.io/s/morning-haze-6dxke?file=/src/App.vue
我写了个例子你可以试一下,单独点变化名字,是会触发变化的,但是点变化年龄并不会触发视图更新

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/663253

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX