更新对象数组

时间:2018-12-19 17:34:24

标签: vue.js

我有一个对象数组items

  data() {
    return {
      items: [
          {
              id: 101,
              firstName: 'Mohammed',
              lastName: 'Chang',
              dob: '1995-03-21'
          },
          {
              id: 102,
              firstName: 'John',
              lastName: 'Smith',
              dob: '1989-10-11'
          },
          {
              id: 103,
              firstName: 'Lulu',
              lastName: 'Lemon',
              dob: '1945-01-29'
          },
      ]
    }
  },

如果我使用常规手表,并尝试比较项目,因为这些项目是对象,它们将引用同一事物,因此它们将始终返回不变:

 watch: {
    items: {
        handler: function(revised, original) {
            for (let i = 0; i < revised.length; i++) {
                // check each item in revised to see if it's changed from original
                if (this.isChanged(original, revised[i])) {
                    axios.put(URL + '/' + revised[i].id, revised[i]);
                }
            }
        },
        deep: true
    }
  },
  methods: {
      isChanged(original, item) {
        // this function won't work because item is an object
        // which will be referenced in original, so it will always
        // be a match, i.e. not changed
        for (let i = 0; i < revised.length; i++) {
          // found a matching ID in the original
          if (original[i].id === revised.id) {
              // compare the item against the original and return
              // true for changed and false for not changed
              return JSON.stringify(original[i]) !== JSON.stringify(item);
          }
          // no match? assume true
          return true;
        }
      }
    }
  }

如果我使用这样的手表,直接引用每个项目,那么它将起作用:

 watch: {
    'items.0': {
        handler: function(revised) {
            axios.put(URL + '/' + revised.id, revised);
        },
        deep: true
    },
    'items.1': {
        handler: function(revised) {
            axios.put(URL + '/' + revised.id, revised);
        },
        deep: true
    },
    'items.2': {
        handler: function(revised) {
             axios.put(URL + '/' + revised.id, revised);
        },
        deep: true
    }
  },

但是这种方法不是很实用。如果我将项目动态添加到数组怎么办?它没有观察者。

是否可以使用通配符或正则表达式来进行类似items.#的监视?

由于无法比较原始对象,大多数开发人员是否仅使用其自己的PUT调用来更新整个数组中的每个元素?这似乎很浪费,尤其是在处理许多非常大的对象时。

 watch: {
    items: {
        handler: function(revised) {
            // no way to know which item is changed, so just
            // update each item - wasteful, I know
            for (let i = 0; i < revised.length; i++) {
                axios.put(URL + '/' + revised[i].id, revised[i]);
            }
        },
        deep: true
    }
  },

1 个答案:

答案 0 :(得分:2)

  

如果我使用常规手表,并尝试比较项目,因为这些项目是对象,它们将引用同一事物,因此它们将始终返回不变:

是的,在这种情况下,您将无法在处理程序中使用以前的值,而只能使用新的值。

  

如果我使用这样的手表,直接引用每个项目,那么它将起作用:

是的,它将。因为您不再看嵌套的对象。

  

但是这种方法不是很实用。如果我将项目动态添加到数组怎么办?它没有观察者。

对,它不会有观察者。

  

有没有办法像上面的项目一样进行监视。#,但使用通配符或正则表达式?

不,没有类似的东西。

  

由于无法比较原始对象,大多数开发人员是否仅使用其自己的PUT调用来更新整个数组中的每个元素?这似乎很浪费,尤其是在处理许多非常大的对象时。

我迷路了...为什么有人应该更新整个数组中的每个元素?您所说的“自己的PUT呼叫”是什么意思?您可以编辑问题并通过该PUT调用给我一些代码示例吗?你能告诉我你想做什么吗?要实现?

编辑

现在我明白了……首先:每个应用程序应该只有一个事实要点。在您的情况下,它是外部数据库,而不是SPA本身。 SPA只是可视化该数据。因此,可以(不仅)解决问题的核心:

从后端获取真实数据。例如,在创建应用程序期间:

new Vue({
  el: '#app',

  data: {
    items: []
  },

  created () {
    this.$axios
      .get('mountpoint')
      .then(({ data }) => {
        this.items = data
      })
  }
}

然后不要直接更改它们。例如,像这样:

新Vue({       el:“#app”,

  data: {
    items: []
  },

  created () {
    this.$axios
      .get('mountpoint')
      .then(({ data }) => {
        this.items = data
      })

    // Bad
    setTimeout(() => {
      this.items[1].firstName = 'Jan'
    }, 2000)
  }
}

但是这样:

新Vue({       el:“#app”,

  data: {
    items: []
  },

  methods: {
    updateItems (idx, obj) {
      this.item[idx] = { ...this.items[idx], ...obj }
    }
  },

  created () {
    this.$axios
      .get('mountpoint')
      .then(({ data }) => {
        this.items = data
      })

    // Good, through some kind of setter
    setTimeout(() => {
      updateItems(1, { firstName': 'Jan' })
    }, 2000)
  }
}

这有什么用?现在,在进行任何更改之前,您可以在该设置器中开始测试与现有值不同的新值。而且不仅如此。如果您检测到某些更改,仍然不要更改items数组。将此更改首先与axios一起发布到后端,并且仅在后端响应更改成功后才更改项目。