VueJS2:如何更新数组中的对象并传回给父对象?

VueJS2: How to update objects in an array and pass back to parent?

我有一个父组件,它正在将一些 API 数据传递给子组件,以便预填充一些输入字段。当用户更改子组件上的某些数据时,该子组件会将数据发送回父组件,我们将在父组件处理它以在用户表单提交时进行服务器提交。

为了处理要处理的更新,我将子数据作为父对象存储在数组(对象数组)中的对象发回。这个数组是我发送给服务器处理的。

我正在为如何更新对象数组中的对象属性而苦恼

Codesandbox:https://codesandbox.io/s/romantic-mestorf-yc0i1h?file=/src/components/Parent.vue

让我详细解释一下。我有 3 个组件:

<App>
    <Parent>
        <Child />
    </Parent>
</App>

App.vue:

    <template>
  <div id="app">
    <form @submit.prevent="submitForm()">
      <Parent
        :localShortNames="formValues.localShortNames"
        @save-form-data="saveFormData"
      />
      <button type="submit">Submit</button>
    </form>
  </div>
</template>

<script>
import Parent from "./components/Parent.vue";
import data from "./assets/data.json"; // <--- will be an actual API request
export default {
  components: {
    Parent,
  },
  data() {
    return {
      formValues: {
        localShortNames: data,
      },
    };
  },
  methods: {
    saveFormData(x) {
      // TO DO
    },
    submitForm() {
      // TO DO: save data to server
    },
  },
};
</script>

Parent.vue:

<template>
  <div>
    <h5>List of Data</h5>
    <Child
      v-for="item in localShortNames"
      :key="item.localSnameID"
      :localShortName="item"
      @save-form-data="saveFormData"
    />
  </div>
</template>

<script>
import Child from "./Child.vue";
export default {
  props: {
    localShortNames: {
      type: Array,
    },
  },
  components: {
    Child,
  },
  data() {
    return {
      newLocalShortNamesArr: this.localShortNames,
    };
  },
  methods: {
    saveFormData(x) {
      let elementId = (el) => el.localSnameID === x.localSnameID;

      const newArr = this.newLocalShortNamesArr.map((obj) => {
        if (elementId) {
          // I need to update the existing object in newLocalShortNamesArr with updated user submitted properties
          // ...
        } else {
          // item does not exist, lets push it to newLocalShortNamesArr
          // TO DO LATER: create "add new data" button for adding new objects to array
    },
  },
},
},
}
</script>

Child.vue:

<template>
  <div>
    <label for="name-input">Name:</label>
    <input
      type="text"
      id="name-input"
      v-model="formValues.name"
      @input="$emit('save-form-data', formValues)"
    />

    <label for="dialect-input">Dialect:</label>
    <input
      type="text"
      id="dialect-input"
      v-model="formValues.iso6393Char3Code"
      @input="$emit('save-form-data', formValues)"
    />
  </div>
</template>

<script>
export default {
  props: {
    localShortName: {
      type: Object,
    },
  },
  data() {
    return {
      formValues: {
        localSnameID: this.localShortName
          ? this.localShortName.localSnameID
          : null,
        name: this.localShortName ? this.localShortName.name : null,
        iso6393Char3Code: this.localShortName
          ? this.localShortName.iso6393Char3Code
          : null,
      },
    };
  },
};
</script>

问题:如果原始数组中存在相同的id,如何处理数组中对象的更新并“覆盖”那些属性(name,和iso6393Char3Code)?

在parent.vue,我想做这样的事情,但我不知道:

    saveFormData(x) {
      // console.log(x);
      let elementId = (el) => el.localSnameID === x.localSnameID;

      const newArr = this.newLocalShortNamesArr.map((obj) => {
        if (elementId) {
          // I need to update the existing object in newLocalShortNamesArr with updated user submitted properties
          // ...
        } else {
          // item does not exist, lets push it to newLocalShortNamesArr
          // ...
        }
      });

这里 Object.assign 会比 map() 更好吗?我想要做的就是向名为 localShortNames 的 API 提供一个数组,其中包含所有对象,无论它们是否已更新。希望这是有道理的!

我这里有一个 codesandbox 上面的代码:https://codesandbox.io/s/romantic-mestorf-yc0i1h?file=/src/components/Parent.vue

第一个问题Parent Component in saveFormData 如果你想检查对象是否存在于数组中,你可以使用 findIndex() 方法循环遍历数组,如果存在则 return 对象索引否则 return -1 如果不存在 如果存在 objectIndex 将大于 -1 并使用子组件中的对象更新该索引,然后我们在更新为 App.vue component

后发出数组
  saveFormData(x) {
      const objectIndex = this.newLocalShortNamesArr.findIndex((ele) => {
            return ele.localSnameID == x.localSnameID
      });
      
      if (objectIndex > -1) {
        // the object exists
        this.newLocalShortNamesArr[objectIndex] = { ...x };
      } else {
        // this case need new html form for add new item in array 
        this.newLocalShortNamesArr.push(x);
      }
      this.$emit("save-form-data", this.newLocalShortNamesArr);
  },

在App.vue组件 我们用从父组件发出的数据更新主数组

 saveFormData(x) {
      this.formValues.localShortNames = [...x];
 },

我用新代码更新了 codesandbox .. 我希望解决方案对您来说很清楚

https://codesandbox.io/s/dreamy-clarke-v04wfl?file=/src/App.vue:595-734