vue怎么监听数组项?

正能量前线
  • 528

如下数组,其中ccc属性值根据bbb属性和ddd属性计算得到的,我需要监听数据项的变化,动态计算ccc属性值

 export default {
        data() {
            return {
                aaa: [{
                   bbb: "xxx",
                   ddd: "xxx",
                   ccc: ""
                }, {
                   bbb: "yyy",
                   ddd: "yyy",
                   ccc: ""
                }]
            }
        }
       
 }

于是我使用了watch监听

 watch: {
            aaa: {
                deep: true,
                handler(newValue, oldValue) {
                    for (let i = 0; i < newValue.length; i++) {
                        newValue[i].ccc = newValue[i].bbb + newValue[i].ddd;
                    }
                }
            }
        }

这种方法会导致每个数据项的变动,需要所有数据项都计算一次,有没有什么好的方式?

而且,还有个问题,监听数组并没法获取到旧值,也就是newValue和oldValue是一模一样的,都是新的值。

这个问题主要是讨论性能问题,比如每个数组有100个属性项,又或者ccc是通过耗性能的计算得到的,那么每次数据项的变动都导致所有数据项重新计算一次,这耗费的性能不可想象,所以大家可以想一下,看有没有好的实现方案?? 实现目标是只对变动的数据项进行计算

回复
阅读 1.3k
8 个回答

https://jsbin.com/meteyuyeqe/...,output
比较简单的方式——过滤器或者直接定义一个getter;
还有一个方式就是将动态计算显示的那个属性抽成组件,传入props通过vue的computed去计算,和直接在数据上定义getter原理上是一样的

用过滤器

<div v-html="aaa[0] | ccc"></div>
filters: {
  ccc(data) {
    return data.bbb + data.ddd;
  }
}

我这有一个比较麻烦的方案,不知道适合不适合你。

data() {
      list: [{
        a: 1,
        b: 2
      }, {
        a: 10,
        b: 20
      }],
      watchList: []
},
created() {
    this.bindWatch(this.list, (i, newVal, oldVal) => {
      this.$set(i, 'c', newVal)
    })
    this.list[1].a = 20
    // 数组改变的时候需要动态添加绑定和解除绑定,有点繁琐。
},
methods: {
    // 给数组添加计算
    bindWatch(ary, hanlder) {
      const watchList = []
      ary.forEach((i) => {
        watchList.push(this.$watch(() => {
          return i.a + i.b
        }, (newVal, oldVal) => {
          hanlder(i, newVal, oldVal)
        }))
      })
      this.watchList = watchList
    },
    // 解除监听
    unBind() {
      this.watchList.forEach(unwatch => {
        unwatch()
      })
    },

}

加个判断,

handler(newValue, oldValue) {
    /**添加的数组项 */
    const added = newValue.filter(a=>!oldValue.includes(a));
    /**删除的数组项 */
    const deleted = oldValue.filter(a=>!newValue.includes(a));
    
    if(added.length > 0){
        // to do
    }

    if(deleted.length > 0){
        // to do
    }
}

这样可能会好点,建议还是用watch

这种方法会导致每个数据项的变动,需要所有数据项都计算一次,有没有什么好的方式?
不用watch 监听 如果只是改一个元素的话直接 o.cc=o.bb+o.cc

监听数组并没法获取到旧值,也就是newValue和oldValue是一模一样的,都是新的值?
初始化的时候 数组aaa 的时候 定义一个 tempCloneAaa = DeepCopy.clone(aaa)
watch 改变后 在 tempCloneAaa = DeepCopy.clone(aaa) 重新赋值
补充
有无id? 页面key指定一下

关于 newValue和oldValue是一模一样的 这个问题我也遇到过。这是因为数组是引用类型,所以 newVal 和 oldVal 指向的都是一个内存地址,所以除非你每次赋值的时候只有把this.aaa 指向另一个地址才行,可以用考虑用深拷贝,但是性能嘛就很一般了=。=

问题的关键是你为什么要这么写
就因为你用的是vue,所以你必须要搞个什么监听来计算结果?
你可以给修改下数据结构给每个对象都定义一个类,然后再他们的自己的类里计算ccc的值。

没有Vue就不能写代码了?

你知道吗?

宣传栏