recherche

Maison  >  Questions et réponses  >  le corps du texte

Composant de case à cocher personnalisé Vue 3 lié à un tableau de valeurs sélectionnées

J'ai essayé de créer un composant simple avec une case à cocher stylée et une étiquette correspondante. Les valeurs (chaînes) de toutes les cases sélectionnées doivent être stockées dans un tableau. Cela fonctionne pour les cases à cocher HTML simples :

<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>

Cela conduit à la situation souhaitée suivante :

Maintenant, si je remplace ces cases à cocher par un composant de case à cocher personnalisé, je n'arrive pas à le faire fonctionner. Si je coche une case, la valeur qu'elle émet semble remplacer le tableau status au lieu d'y être ajoutée ou supprimée, ce qui donne ce qui suit :

Donc, pour une raison quelconque, toutes les cases sont cochées par défaut et lorsque je clique sur l'une d'entre elles, elles sont toutes décochées et la valeur status 值会转到 false ,再次单击任何一个复选框将选中所有复选框并使 status true passe à false. Cliquer à nouveau sur n'importe quelle case sélectionnera toutes les cases et fera < code >statut true.

Maintenant, je sais que renvoyer si la case est cochée dans l'émission renvoie une valeur vraie ou fausse, mais je ne comprends pas comment Vue fait cela avec les cases à cocher natives et comment implémenter ce comportement avec mon composant.

Voici le code de mon composant case à cocher :

<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>

Et le composant parent utilise simplement un modèle différent :

<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>

J'ai essayé de regarder cette réponse de StevenSiebert mais elle utilise un objet et je souhaite reproduire le comportement original de Vue en utilisant des cases à cocher natives.

J'ai également fait référence à la documentation officielle de Vue sur v-model mais je ne comprends pas pourquoi cela fonctionne différemment pour les cases à cocher natives que pour les composants.

P粉561749334P粉561749334363 Il y a quelques jours675

répondre à tous(1)je répondrai

  • P粉893457026

    P粉8934570262023-12-22 15:09:31

    Le modèle V pour chaque case à cocher sera le même, probablement similaire à l'extrait de code suivant :

    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>

    répondre
    0
  • Annulerrépondre