V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
xcstream
V2EX  ›  问与答

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

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

    }
    Sapp
        8
    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
    我写了个例子你可以试一下,单独点变化名字,是会触发变化的,但是点变化年龄并不会触发视图更新
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   982 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 21:55 · PVG 05:55 · LAX 14:55 · JFK 17:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.