【问题标题】:Grabbing data from multiple child components Vue js从多个子组件Vue js中获取数据
【发布时间】:2020-02-10 09:57:21
【问题描述】:

这几天我都在头疼,想弄清楚如何从子组件中获取数据。

情况是这样的。

我有一个名为Post 的父组件,用户可以在其中选择日期、标题、描述,并且可以包含Event 组件的多个实例。 Event 组件包含标题、描述、与会者等字段。

用户应该能够添加多个Eventcomponents,这意味着我在Post 组件中有多个Event 组件。

所以,我不知道如何组合我的组件以在我的 Post 组件中包含一个 Event 对象数组,我以后可以将其发送到我的 API。

我需要的post对象的结构是:

// Post.vue
{ 
    "date": '',
    "name": '',
    "description": '',
    "events": {
       {
        "title": '',
        "description": '',
        "attendees": ''
       },
       {
        "title": '',
        "description": '',
        "attendees": ''
       }
    }
}

所以,我不知道应该以及如何使用 vuex。我尝试使用 $emit 来传递数据,但找不到适合将数据放入 Post 模型的方法。

谁能指出我应该在哪里寻找它?

EDIT #1:添加示例代码

组件代码:

<template>
  <v-form>
    <v-container>
      <v-row>
        <v-col
          cols="12"
          md="4"
        >
          <v-date-picker v-model="post.date" scrollable>
            <v-spacer />
            <v-btn text color="primary" @click="modal = false">
              Cancel
            </v-btn>
            <v-btn text color="primary" @click="$refs.dialog.save(date)">
              OK
            </v-btn>
          </v-date-picker>
        </v-col>

        <v-col
          cols="12"
          md="4"
        >
          <v-text-field
            v-model="post.name"
            label="name"
            required
          />
        </v-col>

        <v-col
          cols="12"
          md="4"
        >
          <v-textarea
            v-model="post.description"
            name="description"
            label="Description"
            dense
            value
            rows="4"
            hint
          />
        </v-col>
      </v-row>
      <v-row>
        <v-btn primary rounded @click="addLine">
          Add Event
        </v-btn>
        <v-expansion-panels accordion>
          <UserEvent
            v-for="(line, index) in lines"
            :key="index"
            @addLine="addLine"
            @removeLine="removeLine(index)"
          />
        </v-expansion-panels>
      </v-row>
    </v-container>
  </v-form>
</template>

<script>
import UserEvent from './partials/event'
export default {
  name: 'Post',
  components: { UserEvent },
  data () {
    return {
      post: [],
      lines: [],
      blockRemoval: true
    }
  },
  watch: {
    lines () {
      this.blockRemoval = this.lines.length <= 1
    }
  },
  mounted () {
  },
  methods: {
    addLine () {
      const checkEmptyLines = this.lines.filter(line => line.number === null)
      if (checkEmptyLines.length >= 1 && this.lines.length > 0) { return }
      this.lines.push({
        title: null,
        description: null,
        attendees: null
      })
    },
    removeLine (lineId) {
      if (!this.blockRemoval) { this.lines.splice(lineId, 1) }
    }
  }
}
</script>

还有子组件UserEvent

// UserEvent.vue
<template>
  <v-expansion-panel>
    <v-expansion-panel-header>Event details</v-expansion-panel-header>
    <v-expansion-panel-content>
      <v-row>
        <v-col cols="12" md="6">
          <v-text-field
            v-model="event.title"
            label="Title"
            required
          />
        </v-col>

        <v-col
          cols="12"
          md="6"
        >
          <v-text-field
            v-model="event.atttendees"
            label="Atendees"
            required
          />
        </v-col>

        <v-col
          cols="12"
          md="12"
        >
          <v-textarea
            v-model="event.description"
            name="description"
            label="Description"
            dense
            value
            rows="4"
            hint
          />
        </v-col>
        <v-col
          cols="12"
          md="3"
        >
          <div class="block float-right">
            <v-btn @click="removeLine(index)" />
            <v-btn v-if="index + 1 === lines.length" @click="addLine" />
          </div>
        </v-col>
      </v-row>
    </v-expansion-panel-content>
  </v-expansion-panel>
</template>

<script>
export default {
  name: 'UserEvent',
  props: ['line', 'index'],
  data () {
    return {
      event: []
    }
  },
  methods: {
    addLine () {
      this.$emit('addLine')
    },
    removeLine (index) {
      this.$emit('removeLine', index)
    }
  }
}
</script>

【问题讨论】:

  • 子元素每次有新数据时可以$emit。父母可以根据需要收集该数据和post 到后端。没有代码示例,这就是我所能做到的最具体的了。
  • 嗨大卫,我已经用示例代码更新了这个问题。我想知道的是:是否可以让UserEvents 与父组件保持同步,或者我只能使用this.$emit 事件来更新父组件?
  • 父组件 Post 应该是唯一负责持有状态的组件。孩子们应该使用 v-model 将用户输入传输到 Post。看看:vuejs.org/v2/guide/components.html#Using-v-model-on-Components(您应该将 Event 组件视为自定义输入)
  • 我也是这么想的。我只是对如何确保从Post 商店更新或删除正确的事件感到困惑。

标签: vue.js vuex nuxt.js


【解决方案1】:

这是一个与问题中提出的结构相似的示例:

{
  name: String,
  events: [
    title: String,
    description: String,
  ],
}

这个例子允许用户打开一个表单来添加一个新事件。当该表单被提交时,事件数据被添加到父组件的状态中。

家长

<template>
  <div>
    <input v-model="name" />
    <ul v-if="events.length">
      <li v-for="(event, index) in events" :key="index">
        <span>{{ event.title }}</span>
        <span>{{ event.description }}</span>
      </li>
    </ul>
    <Event v-if="isNewEventFormVisible" @submit="addEvent" />
    <button v-else @click="showNewEventForm">add event</button>
  </div>
</template>
import Event from '~/components/Event';

export default {
  components: { Event },
  data() {
    return {
      name: 'Example Post',
      events: [],
      isNewEventFormVisible: false,
    };
  },
  methods: {
    addEvent({ title, description }) {
      this.isNewEventFormVisible = false;
      this.events.push({ title, description });
      // TODO: call you API here to update
    },
    showNewEventForm() {
      this.isNewEventFormVisible = true;
    },
  },
};

活动

<template>
  <form @submit.prevent="onSubmit">
    <input v-model.trim="title" type="text" />
    <br />
    <textarea v-model.trim="description" />
    <button type="submit">submit</button>
  </form>
</template>
export default {
  data() {
    return {
      title: '',
      description: '',
    };
  },
  methods: {
    onSubmit() {
      this.$emit('submit', {
        title: this.title,
        description: this.description,
      });
    },
  },
};

您可以想象一个更复杂的版本,其中事件是可编辑的。在这种情况下,每个 Event 都可以使用 props 并将它们作为值绑定到其输入,而不是使用 v-models。

【讨论】:

    猜你喜欢
    • 2021-08-02
    • 1970-01-01
    • 2020-03-31
    • 2020-12-14
    • 2020-09-20
    • 2017-06-25
    • 1970-01-01
    • 2019-01-19
    • 2020-09-25
    相关资源
    最近更新 更多