代码之家  ›  专栏  ›  技术社区  ›  gregwhitworth

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

  •  0
  • gregwhitworth  · 技术社区  · 7 年前

    我看了这个可能的骗局,比如这个 one 它不一定能解决我的问题。

    我的场景是,我有一个带有标签和复选框的orgs组件附加到v模型。该组件将与其他表单组件结合使用。目前,它可以工作-但即使两个复选框都被单击,它也只会将一个值传递回父级。

    表格页:

    <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的伪org。单击两个复选框并单击提交按钮后,selectedorgs数组仅包含2,就好像第二次单击实际上覆盖了第一次单击。我只选中一个框并点击submit,1或2的值就通过了验证。似乎array方法在组件级工作,但在组件到父级上不工作。

    如有任何帮助,我们将不胜感激。

    更新

    多亏了puelo的评论,我将orglisting组件切换为发出附加到v-model的数组,如下所示:

    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的值更新之前被触发,所以它总是落后一个“check”。实际上,我希望emit等待$data对象更新,这可能吗?

    2 回复  |  直到 7 年前
        1
  •  1
  •   puelo    7 年前

    文件 v-model in-form绑定仍然适用于自定义组件,如:

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

    https://vuejs.org/v2/guide/forms.html#Basic-Usage https://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-模型 只听一件事 @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)
    }
    

    这是非常基本的,没有经过测试,但应该给你一个想法,也许可以解决这个问题。

        2
  •  0
  •   gregwhitworth    7 年前

    非常感谢@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>
    

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

    这利用了v-model维护是否检查它们的数组的优势。然后在表单页面上,我只使用 v-on:updateOrgs="updateSelectedOrgs" 它包含填充的数组并维护封装。