Composant API de composition vue 3 avec un tableau de cases à cocher et tout basculer
P粉670838735
2023-08-30 20:55:11
<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>
Il me semble que cela peut être fait d'une manière plus simple.
fooItemsIl devrait probablement y avoir un état initial de « vérifié ».Cliquez simplement
selectedHandler中,只需调用emit().toggleAll最终将创建一个与internalModelFonctions utilisées ensemble.Voici un exemple Vue SFC Playground.
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>