javascript - VueJS : How can I successfully pass arrays from child to parent components

标签 javascript vue.js vuejs2 vue-cli vue-multiselect

我正在使用Vue-Multiselect插件并尝试向父组件发送一些数据,以便后端 API 可以更新一些记录,但我不知道如何成功完成此操作。

这是我对 CodeSandBox Demo 的尝试(以及更详细的解释) 注意:要查看正在运行的多选 UI,请转到 POST-->ACME WIDGET 并单击“编辑”,您可以在其中使用多选插件。

在我的子组件 CustomerPOCSelect.vue 中,有一个 onRemove 事件,它将一些数据推送到名为 pocsToRemove 的数组中。同样,onSelect 事件也将一些数据推送到名为 pocsToAdd 的数组中。

但是,我不确定如何从这一点到达父级 EditPost.vue,因此我可以使用父级的 onSubmitUpdate 事件并进行实际更新服务器。每次用户对多选输入进行更改(无论是删除还是添加)并单击 UPDATE POST 按钮时,我都需要将发出的数据传递给 onSubmitUpdate 方法。

EditPost.vue

<template>
  <div>
    <label>Point of Contacts:</label>
    <multiselect
      v-model="value"
      :options="options"
      label="lastname"
      placeholder="plaeholder text"
      track-by="uid"
      :loading="isLoading"
      :custom-label="selectedNameLabel"
      selectLabel
      :multiple="true"
      @remove="onRemove"
      @select="onSelect"
    >
      <template
        slot="singleLabel"
        slot-scope="props"
      >{{ props.option.lastname }}, {{props.option.firstname}}</template>
      <template slot="option" slot-scope="props">
        <strong>{{ props.option.lastname }}</strong>
        , {{ props.option.firstname }} &mdash;
        <small>{{ props.option.email }}</small>
      </template>
    </multiselect>
    <!-- <small id="searchHelpBlock" class="form-text text-muted"><font-awesome-icon icon="exclamation-circle" /> If customer does not exist, you will be prompted to add a new customer</small> -->
    <!-- <h3>New contacts to be added:</h3>
    <ul>
      <li v-for="value in values" :key="value.uid">{{value.lastname}}, {{value.firstname}}</li>
    </ul>-->
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";
// import ApiService from "@/apiService";
export default {
  components: { Multiselect },
  props: ["users", "post", "contacts"],
  data() {
    return {
      value: this.contacts,
      options: this.users,
      isLoading: true,
      pocsToRemove: [],
      pocsToAdd: []
    };
  },
  created() {
    this.isLoading = false;
  },
  methods: {
    selectedNameLabel(option) {
      return `${option.lastname}, ${option.firstname} -- ${option.email}`;
    },
    onRemove(option) {
      this.pocsToRemove.push(Number(option.uid));
    },
    onSelect(option) {
      this.pocsToAdd.push(Number(option.uid));
    }
  }
};
</script>

CustomerPOCSelect.vue

<template>
  <div>
    <form @submit.prevent="onSubmitUpdate" v-if="!$route.params.addPost">
      <h3>Update Post</h3>
      <div>
        <label for="product_name_input">Post Name:</label>
        <br>
        <input type="text" v-model="post.post_name" id="post_name_input" required>
      </div>
      <br>
      <br>
      <CustomerPOCSelect :users="userProfiles" :post="post" :contacts="contacts"/>
      <br>
      <button type="submit" v-if="!loading">Update Post</button>
      <button type="button" disabled v-if="loading">
        <span role="status" aria-hidden="true"></span>
        Updating...
      </button>
      <button @click.prevent="cancelEdit">Cancel Edit</button>
    </form>
    <form v-if="$route.params.addPost">
      <h3>Add New Post</h3>
      <div>
        <label for="product_name_input">Post Name:</label>
        <br>
        <input type="text" v-model="post.post_name" id="post_name_input" required>
      </div>
      <br>
      <button type="submit" v-if="!loading">Add Post</button>
      <button type="button" disabled v-if="loading">
        <span role="status" aria-hidden="true"></span>
        Adding...
      </button>
      <button @click.prevent="cancelEdit">Cancel Edit</button>
    </form>
  </div>
</template>

<script>
import CustomerPOCSelect from "@/components/CustomerPOCSelect.vue";
export default {
  props: ["id"],
  components: {
    CustomerPOCSelect
  },
  data() {
    return {
      post: {
        post_name: "",
        post_id: null,
        poc_list: []
      },
      posts: [
        {
          post_id: 1,
          process_id: 4,
          post_name: "ACME Widget",
          poc_list: [1, 2]
        },
        {
          post_id: 2,
          process_id: 1,
          post_name: "XYZ Widget",
          poc_list: [3]
        },
        {
          post_id: 3,
          process_id: 2,
          post_name: "ABC Bar",
          poc_list: []
        },
        {
          post_id: 4,
          process_id: 3,
          post_name: "Foo Bar",
          poc_list: [1, 3]
        }
      ],
      userProfiles: [
        {
          uid: "1",
          firstname: "Claiborne",
          lastname: "Heberden",
          email: "cheberden0@gravatar.com"
        },
        {
          uid: "2",
          firstname: "Gerick",
          lastname: "Tetla",
          email: "gtetla1@whitehouse.gov"
        },
        {
          uid: "3",
          firstname: "Raymund",
          lastname: "Espy",
          email: "respy2@freewebs.com"
        },
        {
          uid: "4",
          firstname: "Dilly",
          lastname: "Dimitriev",
          email: "ddimitriev3@skype.com"
        },
        {
          uid: "5",
          firstname: "Roby",
          lastname: "Tabner",
          email: "rtabner4@sohu.com"
        },
        {
          uid: "6",
          firstname: "Jeff",
          lastname: "Smith",
          email: "jsmith@sohu.com"
        },
        {
          uid: "7",
          firstname: "Damn",
          lastname: "Man",
          email: "dman4@sohu.com"
        }
      ],
      loading: false,
      btnDisable: true
    };
  },
  created() {
    this.populateFields();
  },
  methods: {
    populateFields() {
      // this.post.post_id = this.$route.params.addPost
      //   ? null
      //   : this.$route.params.post_id;
      this.post.post_name = this.$route.params.addPost
        ? ""
        : this.$route.params.post_name;
      this.post.poc_list = this.$route.params.addPost
        ? null
        : this.$route.params.poc_list;
    },
    removePOC(x) {
      this.post.poc_list.push(x);
    },
    // onSubmitUpdate() {
    //   this.loading = true
    //   ApiService.updatePost(this.post)
    //     .then(() => {
    //       this.loading = false
    //       this.$router.push({ path: '/' })
    //     })
    //     .catch(err => {
    //       if (err.response) {
    //         this.errors = err.response.data
    //       } else {
    //         if (err.request) {
    //           this.errors = err.request
    //         } else {
    //           this.errors = err.message
    //         }
    //       }
    //       this.loading = false
    //       console.error('Error from update', err)
    //     })
    // },
    cancelEdit() {
      this.$router.push({ path: "/posts" });
    }
  },
  computed: {
    contacts() {
      const post = this.posts.find(post => post.post_id === this.id);
      // all user names
      return this.userProfiles.filter(user => {
        return post.poc_list && post.poc_list.includes(Number(user.uid));
      });
    }
  }
};
</script>

最佳答案

您可以使用Vuex自定义事件来实现此目的,这是自定义事件使用的示例

父组件

...
<ChildComponent @toParent="handler"/>

methods: {
  handler(value) {
    // Log Data From Child Component
    console.log(value) // "Dummy Data"
  },
}
...

子组件

...
data() {
  return {
    myData: "Dummy Data"
  }
},
mounted() {
  // You can emit this anywhere, it doesn't have to be in mounted
  this.$emit('toParent', this.myData)
},
...

关于javascript - VueJS : How can I successfully pass arrays from child to parent components,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60086895/

相关文章:

vue.js - 如何从文件夹中导入所有 Vue 组件?

javascript - Vue Js 过滤器不起作用

javascript - JSHint:不要在循环内创建函数

javascript - 弃用移动应用程序上的触摸操作

css - 关于移动 safari 渲染问题的任何想法

javascript - 使用 Vue.js 和 Vue CLI 3 进行一些处理后通过 props 渲染项目

javascript - vue js : Prevent Sort from sorting array items, 我只需要结果

javascript - 如何在闭包中公开代码以便可以使用 Jasmine 进行单元测试?

javascript - JSON.stringify 的操作顺序

vue.js - 如何直接在 VueX 状态下设置值