我一直在尝试创建一个带有样式复选框和相应标签的简单组件。所有选定复选框的值(字符串)应存储在一个数组中。这适用于纯 html 复选框:
<template> <div> <div class="mt-6"> <div> <input type="checkbox" value="EVO" v-model="status" /> <label for="EVO">EVO</label> </div> <div> <input type="checkbox" value="Solist" v-model="status" /> <label for="Solist">Solist</label> </div> <div> <input type="checkbox" value="SPL" v-model="status" /> <label for="SPL">SPL</label> </div> </div> <div class="mt-3">{{status}}</div> </div> </template> <script setup> import { ref } from 'vue' let status = ref([]); </script>
它会导致以下所需的情况:
现在,如果我用自定义复选框组件替换这些复选框,我将无法使其工作。如果我选中一个框,它发出的值似乎会替换 status
数组,而不是添加到其中或从中删除,从而导致以下结果:
因此,由于某种原因,默认情况下会选中所有复选框,当我单击其中一个复选框时,它们都会被取消选中,并且 status
值会转到 false
,再次单击任何一个复选框将选中所有复选框并使 status
true
。
现在,我知道在发射中返回是否选中该框会返回 true 或 false 值,但我不明白 Vue 如何使用本机复选框执行此操作以及如何使用我的组件实现此行为。 p>
这是我的复选框组件的代码:
<template> <div class="mt-1 relative"> <input type="checkbox" :id="id ?? null" :name="name" :value="value" :checked="modelValue ?? false" class="bg-gray-200 text-gold-500 rounded border-0 w-5 h-5 mr-2 focus:ring-2 focus:ring-gold-500" @input="updateValue" /> {{ label }} </div> </template> <script setup> const props = defineProps({ id: String, label: String, name: String, value: String, errors: Object, modelValue: Boolean, }) const emit = defineEmits(['update:modelValue']) const updateValue = function(event) { emit('update:modelValue', event.target.checked) } </script>
并且父组件仅使用不同的模板:
<template> <div> <div class="mt-6"> <Checkbox v-model="status" value="EVO" label="EVO" name="status" /> <Checkbox v-model="status" value="Solist" label="Solist" name="status" /> <Checkbox v-model="status" value="SPL" label="SPL" name="status" /> </div> <div class="mt-3">{{status}}</div> </div> </template>
我试图查看 StevenSiebert 的这个答案,但它使用一个对象,我想使用本机复选框复制原始的 Vue 行为。
我还参考了 v-model
上的官方 Vue 文档,但不明白为什么这对于本机复选框的工作方式与对于组件的工作方式不同。
P粉8934570262023-12-22 15:09:31
每个复选框的 v-model 都是相同的,可能类似于以下代码片段:
const { ref } = Vue const app = Vue.createApp({ setup() { const status = ref([{label: 'EVO', status: false}, {label: 'Solist', status: false}, {label: 'SPL', status: false}]) return { status } }, }) app.component('Checkbox', { template: ` <div class="mt-1 relative"> <input type="checkbox" :id="id ?? null" :name="name" :value="value" :checked="modelValue ?? false" class="bg-gray-200 text-gold-500 rounded border-0 w-5 h-5 mr-2 focus:ring-2 focus:ring-gold-500" @input="updateValue" /> {{ label }} </div> `, props:{ id: String, label: String, name: String, value: String, errors: Object, modelValue: Boolean, }, setup(props, {emit}) { const updateValue = function(event) { emit('update:modelValue', event.target.checked) } return { updateValue } } }) app.mount('#demo')
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.18/tailwind.min.css" integrity="sha512-JfKMGsgDXi8aKUrNctVLIZO1k1iMC80jsnMBLHIJk8104g/8WTaoYFNXWxFGV859NY6CMshjktRFklrcWJmt3g==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script> <div id="demo"> <div> <div class="mt-6" v-for="box in status"> <Checkbox v-model="box.status" :value="box.label" :label="box.label" name="status"></Checkbox> </div> <div class="mt-3">{{status}}</div> </div> </div>