Vue 3-Kompositions-API-Komponente mit einer Reihe von Kontrollkästchen und allen umschaltbar
P粉670838735
P粉670838735 2023-08-30 20:55:11
0
1
652
<p>Wir haben beschlossen, mithilfe von Typoskript schrittweise von Knockout zur Vue 3-Kompositions-API überzugehen, und ich versuche, das Anti-Muster mutierender Requisiten zu verstehen. Ich habe eine Arbeitskomponente, die ihre beabsichtigte Aufgabe erfüllt, aber im Grunde möchte ich bestätigen, dass die Art und Weise, wie sie geschrieben ist, der empfohlene Ansatz ist. </p> <p>Ein recht einfaches Beispiel ist eine Kontrollkästchen-Listenkomponente mit einem Schalter darauf: </p> <p>Meine größte Frage ist, ob das, was ich in AppList.vue mache, korrekt ist. Ich mache <code>const internalModel = toRef(props.selected ?? []);</code> Die nicht verfügbaren Variablen in Komponenten und <code>selectedHandler</code> - Ereignisse und <code>toggleAll</code> - werden ausgewertet, um OUT auszugeben, aber hier behalte ich <code>selected</code> ;Interne Modell</Code> Die Verwendung zweier Variablen für dieselbe Sache erscheint umständlich, macht aber gleichzeitig auch Sinn, da das interne Modell die Ansicht nicht beeinträchtigen muss. </p> <p>Ich weiß, dass es auf vuejs.org ein Beispiel gibt, in dem Sie ein Array auf <code>v-model</code> verwenden können, um mehrere Kontrollkästchen darzustellen, aber es befindet sich nicht innerhalb einer Komponente oder als Requisite, also Nicht ganz dasselbe, das fühlt sich komplizierter an. Ich habe den größten Teil des Tages damit verbracht, es richtig zu machen, aber es gibt nicht so viele Vue-3-Suchergebnisse und ich habe überhaupt keine Ergebnisse für dieses spezielle Problem gefunden. </p> <p>HomeView.vue:</p> <p> <pre class="brush:html;toolbar:false;"><script set lang="ts"> import { ref } aus 'vue'; import AppList, { type Item } from '@/components/AppList.vue'; const fooItems = ref<Item[]>([ { id: 1, name: 'foo 1' }, { id: 2, name: 'foo 2' }, { id: 3, name: 'foo 3' }, { id: 4, name: 'foo 4' }, { id: 5, name: 'foo 5' }, ]); const fooSelected = ref<number[]>([]); </script> <Vorlage> <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;"><script setup lang="ts"> import { berechnet, toRef } aus 'vue'; Exportschnittstelle Element { ID: Nummer; Name: Zeichenfolge; } const props = defineProps<{ Artikel: Artikel[]; ausgewählt?: Zahl[]; }>(); const internalModel = toRef(props.selected ?? []); const emit = defineEmits<{ 'update:selected': [selected: number[]]; }>(); const selectedHandler = (e: Event) => { const target = <HTMLInputElement>e.target; if (props.selected && target) { if (target.checked) { emit('update:selected', [...props.selected, Number(target.value)]); } anders { emittieren( 'Update:ausgewählt', props.selected.filter((i: number) => i !== Number(target.value)) ); } } }; const toggleAll = berechnet({ get: () => internalModel.value.length === props.items.length && internalModel.value.every((s) => props.items.map((item) => item.id).includes(s)), set: (Wert) => { if (Wert) { emittieren( 'Update:ausgewählt', props.items.map((i) => i.id) ); internalModel.value = props.items.map((i) => i.id); } anders { emit('update:selected', []); internalModel.value = []; } }, }); </script> <Vorlage> <Label> <input type="checkbox" v-model="toggleAll" /> Alles umschalten </label> <ul> <li v-for="item in items" :key="item.id"> <Label> <input type="checkbox" :value="item.id" v-model="internalModel" @change="selectedHandler" /> <span>id {{ item.name }}</span> </label> </li> </ul> internalModel: {{ internalModel }} </template></pre> </p>
P粉670838735
P粉670838735

Antworte allen(1)
P粉203792468

在我看来,这可以以某种更简单的方式完成。
fooItems 可能应该有一个初始状态“已检查”。
selectedHandler中,只需调用emit()即可。
toggleAll 最终将创建一个与 internalModel 配合使用的函数。
这是一个示例 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>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage