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

Composant API de composition vue 3 avec un tableau de cases à cocher et tout basculer

<p>Nous avons décidé de passer progressivement de KO à l'API de composition vue 3 en utilisant TypeScript, et j'essaie de comprendre l'anti-modèle des accessoires en mutation. J'ai un composant fonctionnel qui fait le travail prévu, mais fondamentalement, je veux confirmer que la façon dont il est écrit est l'approche recommandée. </p> <p>Un exemple assez simple est un composant de liste de cases à cocher avec une bascule : </p> <p>Ma plus grande question est de savoir si ce que je fais dans AppList.vue est correct, je fais <code>const internalModel = toRef(props.selected ?? []);</code> les variables indisponibles dans les composants et <code>selectedHandler</code> - événements et <code>toggleAll</code> - évaluent pour émettre OUT mais ici, je garde manuellement <code>selected</code> ;Modèle interne</Code> Utiliser deux variables pour la même chose semble fastidieux, mais en même temps, cela a du sens puisque le modèle interne n'a pas besoin d'interférer avec la vue. </p> <p>Je sais qu'il existe un exemple sur vuejs.org où vous pouvez utiliser un tableau sur <code>v-model</code> pour représenter plusieurs cases à cocher, mais ce n'est pas à l'intérieur d'un composant ou comme accessoire, donc Ce n’est pas exactement la même chose, cela semble plus compliqué. J'ai passé la majeure partie de la journée à essayer de bien faire les choses, mais il n'y a pas beaucoup de résultats de recherche vue 3 et je n'ai trouvé aucun résultat pour ce problème particulier. </p> <p>HomeView.vue :</p> <p> <pre class="brush:html;toolbar:false;"><ensemble de scripts lang="ts"> importer { ref } depuis 'vue' ; importez AppList, { tapez Item } depuis '@/components/AppList.vue' ; const fooItems = ref<Item[]>([ { identifiant : 1, nom : 'foo 1' }, { identifiant : 2, nom : 'foo 2' }, { identifiant : 3, nom : 'foo 3' }, { identifiant : 4, nom : 'foo 4' }, { identifiant : 5, nom : 'foo 5' }, ]); const fooSelected = ref<numéro[]>([]); </script> <modèle> <AppList :items="fooItems" v-model:selected="fooSelected"></AppList> <div>fooselected : {{ fooSelected }}</div> </template></pre> </p> <p>组件/Applist.vue:</p> <p> <pre class="brush:html;toolbar:false;"><configuration du script lang="ts"> importer { calculé, toRef } depuis 'vue' ; interface d'exportation Article { identifiant : numéro ; nom : chaîne ; } const props = définirProps<{ éléments : élément [] ; sélectionné?: numéro[]; }>(); const internalModel = toRef(props.selected ?? []); const émet = définirEmits<{ 'mise à jour : sélectionné ' : [sélectionné : numéro []] ; }>(); const selectedHandler = (e: Événement) => { const target = <HTMLInputElement>e.target; if (props.selected && target) { si (target.checked) { submit('update:selected', [...props.selected, Number(target.value)]); } autre { émettre( 'mise à jour : sélectionnée', props.selected.filter((i: number) => i !== Number(target.value)) ); } } } ; const toggleAll = calculé ({ obtenir : () => internalModel.value.length === props.items.length && internalModel.value.every((s) => props.items.map((item) => item.id).includes(s)), définir : (valeur) => { si (valeur) { émettre( 'mise à jour : sélectionnée', props.items.map((i) => i.id) ); internalModel.value = props.items.map((i) => i.id); } autre { émettre('mise à jour:sélectionné', []); internalModel.value = []; } }, }); </script> <modèle> <étiquette> <input type="checkbox" v-model="toggleAll" /> tout basculer </étiquette> <ul> <li v-for="élément dans les éléments" :key="item.id"> <étiquette> <input type="checkbox" :value="item.id" v-model="internalModel" @change="selectedHandler" /> <span>id {{ item.name }}</span> </étiquette> ≪/li> </ul> Modèle interne : {{ Modèle interne }} </template></pre> </p>
P粉670838735P粉670838735415 Il y a quelques jours592

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

  • P粉203792468

    P粉2037924682023-08-31 15:28:23

    Il me semble que cela peut être fait d'une manière plus simple.
    fooItems Il devrait probablement y avoir un état initial de « vérifié ».
    Cliquez simplement selectedHandler中,只需调用emit().
    toggleAll 最终将创建一个与 internalModel Fonctions utilisées ensemble.
    Voici un exemple Vue SFC Playground. < /p>


    HomeView.vue :

    <script setup lang="ts">
    import { ref } from 'vue';
    import AppList, { type Item } from './AppList.vue';
    
    const fooItems = ref<Item[]>([
      { id: 1, name: 'foo 1', checked: false },
      { id: 2, name: 'foo 2', checked: false },
      { id: 3, name: 'foo 3', checked: false },
      { id: 4, name: 'foo 4', checked: false },
      { id: 5, name: 'foo 5', checked: true },
    ]);
    const fooSelected = ref<number[]>([]);
    fooItems.value.map(item => item.checked && fooSelected.value.push(item.id))
    </script>
    
    <template>
      <AppList :items="fooItems" v-model:selected="fooSelected"></AppList>
      <div>fooselected: {{ fooSelected }}</div>
    </template>

    AppList.view :

    <script setup lang="ts">
    import { ref } from 'vue';
    
    export interface Item {
      id: number;
      name: string;
      checked: boolean
    }
    
    const props = defineProps<{
      items: Item[];
      selected: number[]
    }>();
    
    const emit = defineEmits(['update:selected']);
    
    const internalModel = ref(props.selected);
      
    const selectedHandler = () => emit('update:selected', internalModel.value);
    
    const toggleAll = ($event) => {
      internalModel.value = [];
      if ( ($event.target as HTMLInputElement).checked ) {
        props.items.map(item => internalModel.value.push(item.id));
      }
      emit('update:selected', internalModel.value);
    };
    </script>
    
    <template>
      <label>
        <input type="checkbox" @change="toggleAll($event)" :checked="internalModel.length === items.length" />
        toggle all
      </label>
      <ul>
        <li v-for="item in items" :key="item.id">
          <label>
            <input type="checkbox" :value="item.id" v-model="internalModel" @change="selectedHandler(item.id)" :checked="item.checked"/>
            <span>{{ item.name }}</span>
          </label>
        </li>
      </ul>
      internalModel: {{ internalModel }}
    </template>

    répondre
    0
  • Annulerrépondre