vuejs将复选框数组传递给父模板仅传递一个值

时间:2018-07-14 22:28:43

标签: javascript vue.js

我查看了诸如此类的one这样的潜在虚假信息,但不一定能解决我的问题。

我的情况是我有一个带有标签和复选框附加到v模型的orgs组件。该组件将与其他表单组件结合使用。目前,它可以正常工作-但即使同时选中了两个复选框,也只能将一个值传递回父级。

表单页面:

<template>
  <section>
    <h1>Hello</h1>
    <list-orgs v-model="selectedOrgs"></list-orgs>
    <button type="submit" v-on:click="submit">Submit</button>
  </section>
</template>

<script>
// eslint-disable-next-line
import Database from '@/database.js'
import ListOrgs from '@/components/controls/list-orgs'

export default {
  name: 'CreateDb',
  data: function () {
    return {
      selectedOrgs: []
    }
  },
  components: {
    'list-orgs': ListOrgs,
  },
  methods: {
    submit: function () {
      console.log(this.$data)
    }
  }
}
</script>

选择组织组件

<template>
  <ul>
    <li v-for="org in orgs" :key="org.id">
      <input type="checkbox" :value="org.id" name="selectedOrgs[]" v-on:input="$emit('input', $event.target.value)"  />
      {{org.name}}
    </li>
  </ul>
</template>

<script>
import {db} from '@/database'

export default {
  name: 'ListOrgs',
  data: () => {
    return {
      orgs: []
    }
  },
  methods: {
    populateOrgs: async function (vueObj) {
      await db.orgs.toCollection().toArray(function (orgs) {
        orgs.forEach(org => {
          vueObj.$data.orgs.push(org)
        })
      })
    }
  },
  mounted () {
    this.populateOrgs(this)
  }
}
</script>

当前,数据库中有两个伪组织,其ID为1和2。单击两个复选框并单击“提交”按钮后,selectedOrgs数组仅包含2,就好像第二次单击实际上是重写了第一次单击一样。我已经通过仅选中一个复选框并单击Submit验证了这一点,并传递了1或2的值。数组方法似乎可以在组件级别上使用,而不能在父级组件上使用。

感谢您的帮助。

更新

由于来自puelo的评论,我切换了orgListing组件以发出附加到v模型的数组,如下所示:

export default {
  name: 'ListOrgs',
  data: () => {
    return {
      orgs: [],
      selectedOrgs: []
    }
  },
  methods: {
    populateOrgs: async function (vueObj) {
      await db.orgs.toCollection().toArray(function (orgs) {
        orgs.forEach(org => {
          vueObj.$data.orgs.push(org)
        })
      })
    },
    updateOrgs: function () {
      this.$emit('updateOrgs', this.$data.selectedOrgs)
    }
  },
  mounted () {
    this.populateOrgs(this)
  }
}

然后在另一端,我只是console.log()返回。这个“有效”但是有一个缺点,似乎$ emit在selectedOrgs的值被更新之前就已经被触发了,因此它总是落后于一个“检查”。实际上,我希望emission等待$ data对象已更新,这可能吗?

2 个答案:

答案 0 :(得分:1)

v-model的表单绑定文档仍然适用于自定义组件,如:

  

v-model本质上是语法糖,用于更新用户输入上的数据   事件...

https://vuejs.org/v2/guide/forms.html#Basic-Usagehttps://vuejs.org/v2/guide/components-custom-events.html#Customizing-Component-v-model

所以在您的代码中

<list-orgs v-model="selectedOrgs"></list-orgs>

被翻译为:

<list-orgs :value="selectedOrgs" @input="selectedOrgs = $event.target.value"></list-orgs>

这意味着v-on:input="$emit('input', $event.target.value)内部的每个发射实际上仅使用单个值(即复选框的状态)覆盖数组。

编辑以解决评论:

也许根本不使用v-model,而只收听@orgSelectionChange="onOrgSelectionChanged"之类的事件。

然后,您可以发出一个带有复选框状态和组织ID的对象(以防止重复):

v-on:input="$emit('orgSelectionChanged', {id: org.id, state: $event.target.value})"

最后,另一端的方法检查重复项:

onOrgSelectionChanged: function (orgState) {
    const index = selectedOrgs.findIndex((org) => { return org.id === orgState.id })
    if (index >= 0) selectedOrgs.splice(index, 1, orgState)
    else selectedOrgs.push(orgState)
}

这是非常基础的,未经测试,但是应该让您了解如何解决此问题。

答案 1 :(得分:0)

非常感谢@puelo的帮助,它有助于澄清一些问题,但不一定能解决我的问题。我想要的是在填充数组的复选框上v-model的简单性,然后将其全部传递给父级,同时保持封装。

所以,我做了一个小小的改变:

选择组织组件

<template>
  <ul>
    <li v-for="org in orgs" :key="org.id">
      <input type="checkbox" :value="org.id" v-model="selectedOrgs" name="selectedOrgs[]" v-on:change="updateOrgs"  />
      {{org.name}}
    </li>
  </ul>
</template>

<script>
import {db} from '@/database'

export default {
  name: 'ListOrgs',
  data: () => {
    return {
      orgs: []
    }
  },
  methods: {
    populateOrgs: async function (vueObj) {
      await db.orgs.toCollection().toArray(function (orgs) {
        orgs.forEach(org => {
          vueObj.$data.orgs.push(org)
        })
      })
    },
    updateOrgs: function () {
      this.$emit('updateOrgs', this.$data.selectedOrgs)
    }
  },
  mounted () {
    this.populateOrgs(this)
  }
}
</script>

表单页面

<template>
  <section>
    <h1>Hello</h1>
    <list-orgs v-model="selectedOrgs" v-on:updateOrgs="updateSelectedOrgs"></list-orgs>
    <button type="submit" v-on:click="submit">Submit</button>
  </section>
</template>

<script>
// eslint-disable-next-line
import Database from '@/database.js'
import ListOrgs from '@/components/controls/list-orgs'

export default {
  name: 'CreateDb',
  data: function () {
    return {
      selectedOrgs: []
    }
  },
  components: {
    'list-orgs': ListOrgs
  },
  methods: {
    updateSelectedOrgs: function (org) {
      console.log(org)
    },
    submit: function () {
      console.log(this.$data)
    }
  }
}
</script>

这里的主要变化是,当我单击复选框并通过this。$ emit('updateOrgs',this。$传递整个updateOrgs数组时,我现在启动一种selectedOrgs方法。 data.selectedOrgs)`

这利用了v模型维护是否检查数组的优势。然后,在表单页面上,我只需使用v-on:updateOrgs="updateSelectedOrgs"来侦听组件上的此事件,该事件包含已填充的数组并保持封装。