VueJS:如何成功将数组从子组件传递到父组件

时间:2020-02-06 02:25:11

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

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

这是我尝试使用CodeSandBox Demo 进行的尝试(以及更详细的解释)注意:要查看运行中的多选UI,请转至POST-> ACME WIDGET,然后单击“编辑”,在此处可以弄乱使用multiselect插件。

在我的子组件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>

1 个答案:

答案 0 :(得分:2)

您可以为此使用Vuex自定义事件,这是自定义事件用法的示例

父组件

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

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

ChildComponent

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