vue computed,对象里的一个数组属性变了,不会执行

如题,合计后面的字段是computed里的receivableItemCnyTotal,现在我detail.receivableList里的invoiceAmountCny 改变了,但是computed不执行是怎么回事
image.png

computed: {
      receivableItemCnyTotal () {
        let total = 0
        if (!this.detail.receivableList || this.detail.receivableList.length === 0) {
          return 0
        }
        this.detail.receivableList.forEach(item => {
          if (item.invoiceAmountCny) {
            total += item.invoiceAmountCny
          }
        })
        return total
      }
    },
receivableItemColumns: [{
          title: '业务编号',
          key: 'businessNo'
        }, {
          title: '费用名',
          key: 'feeItemName'
        }, {
          title: '委托人',
          key: 'receiveFromName'
        }, {
          title: '币别',
          key: 'currency'
        }, {
          title: '总金额',
          key: 'amount'
        }, {
          title: '汇率',
          key: 'exchangeRate',
          render: (h, params) => {
            let found = _this.exchangeRateTemp.find(element => {
              return element.currency === _this.detail.receivableList[params.index].currency
            })
            if (found) {
              _this.detail.receivableList[params.index].exchangeRate = found.exchangeRate
              return h('span', found.exchangeRate)
            }
            return h('span', '')
          }
        }, {
          title: '未开票金额',
          key: 'notInvoicedAmount',
          render: (h, params) => {
            let invoicedAmount = 0
            if (_this.detail.receivableList[params.index].invoiceAmount) {
              invoicedAmount = _this.detail.receivableList[params.index].invoiceAmount
            }
            let notInvoicedAmount = params.row.amount - invoicedAmount - params.row.otherInvoicedAmount
            return h('span', notInvoicedAmount)
          }
        }, {
          title: '当前开票金额',
          key: 'invoiceAmount',
          render: (h, params) => {
            return h('div', [
              h('InputNumber', {
                props: {
                  size: 'small',
                  value: params.row.invoiceAmount,
                  min: 0,
                  max: params.row.amount - params.row.otherInvoicedAmount,
                },
                on: {
                  'on-change': e => {// eslint-disable-line
                    _this.detail.receivableList[params.index].invoiceAmount = e
                  },
                },
              }),
            ])
          },
        }, {
          title: '当前开票金额(¥)',
          key: 'invoiceAmountCny',
          render: (h, params) => {
            let invoicedAmount = 0
            if (_this.detail.receivableList[params.index].invoiceAmount) {
              invoicedAmount = _this.detail.receivableList[params.index].invoiceAmount
            }
            let invoiceAmountCny = invoicedAmount * _this.detail.receivableList[params.index].exchangeRate
            _this.detail.receivableList[params.index].invoiceAmountCny = invoiceAmountCny
            return h('span', invoiceAmountCny)
          },
        }, {
          title: '税率',
          key: 'taxRate'
        }, {
          title: '税额(¥)',
          key: 'taxAmount'
        }]
阅读 10k
3 个回答

===========作者的答案=============
原型上的数据没有改变,因为初始化的时候这个属性不存在

this.$set(_this.detail.receivableList[params.index], 'invoiceAmountCny', invoiceAmountCny)

image.png

你这里对象的invoiceAmount属性并没有改变,你改变的只是InputNumber输入框的内容,因为你的change事件注册错了。

on里面直接写事件名就可以了,不需要再加on-,另外e是event事件对象,你直接赋值给invoiceAmount属性也不大合适

说实话有点没太看懂问题,我再复述一遍

问题

你的合计总量是通过计算属性得到的,计算属性依赖的是数据中的invoiceAmountCny属性,也就是表格中的当前开票金额,然后你发现返回的数据也就是你图片中表格下面的 JSON 数据中第二条的 invoiceAmountCny由 13 变成了 1,但是你的计算属性却没有响应式的更新,也就是你的合计结果没变,对吗?如果我的描述对的话,问题就很明显了

答案

计算属性的结果没变,是正确的,因为计算属性的改变是依赖与 Vue 的响应式系统的,你这里的数据改变没有触发响应式更新,虽然你的 JSON 数据确实显示从 13 变成了 1,但是你看你的表格数据中的第二条依旧是 13,所以你的数据更新没有触发 Vue 的响应式系统

分析

这里的问题应该是你更新数组的方法有问题,Vue 中数组的响应式是通过劫持 Array.prototype 属性上的 7 个操作数组的方法实现的,比如 push、pop、splice 等,或者使用 Vue.set 方法更新也可以

总结

你问题应该就是出在了更新数组数据上,数组的数据更新没有触发 Vue 的响应式系统,建议查看更新数组内容的代码,如果你发现表格数据中的第二条 13 也变成了 1 那结果就对了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏