Eine kurze Diskussion über die Rolle von Vue3 defineComponent

Eine kurze Diskussion über die Rolle von Vue3 defineComponent

Die Funktion „defineComponent“ kapselt einfach die Setup-Funktion und gibt ein Optionsobjekt zurück.

Exportfunktion defineComponent(Optionen: unbekannt) {
  returniere isFunction(Optionen) ? { setup: Optionen } : Optionen
}

Das Wichtigste an defineComponent ist, dass es der Komponente in TypeScript die richtige Parametertypinferenz verleiht.

Bildbeschreibung hier einfügen

defineComponent-Überladungsfunktion

1: Direkt-Setup-Funktion

// Überladung 1: Direkt-Setup-Funktion
// (verwendet benutzerdefinierte Props-Schnittstelle)
Exportfunktion defineComponent<Props, RawBindings = Objekt>(
  aufstellen: (
    Requisiten: Nur lesbar<Requisiten>,
    ctx: Setup-Kontext
  ) => RawBindings | Renderfunktion
): DefineComponent<Props, RawBindings>

Bildbeschreibung hier einfügen

2: Objektformat ohne Requisiten

// Überladung 2: Objektformat ohne Requisiten
// (verwendet benutzerdefinierte Props-Schnittstelle)
// Rückgabetyp ist für Vetur- und TSX-Unterstützung
Exportfunktion defineComponent<
  Requisiten = {},
  RawBindings = {},
  D = {},
  C erweitert ComputedOptions = {},
  M erweitert MethodOptions = {},
  Mixin erweitert ComponentOptionsMixin = ComponentOptionsMixin,
  Erweitert erweitert ComponentOptionsMixin = ComponentOptionsMixin,
  E erweitert EmitsOptions = EmitsOptions,
  EE erweitert Zeichenfolge = Zeichenfolge
>(
  Optionen: ComponentOptionsWithoutProps<Props,RawBindings,D,C,M,Mixin,Extends,E,EE>
): DefineComponent<Props, RawBindings, D, C, M, Mixin, Extends, E, EE>

Bildbeschreibung hier einfügen

3: Objektformat mit Array-Props-Deklaration

// Überladung 3: Objektformat mit Array-Props-Deklaration
// Requisiten abgeleitet als { [Schlüssel in PropNames]?: beliebig }
// Rückgabetyp ist für Vetur- und TSX-Unterstützung
Exportfunktion defineComponent<
  PropNames erweitert String,
  Rohbindungen,
  D,
  C erweitert ComputedOptions = {},
  M erweitert MethodOptions = {},
  Mixin erweitert ComponentOptionsMixin = ComponentOptionsMixin,
  Erweitert erweitert ComponentOptionsMixin = ComponentOptionsMixin,
  E erweitert EmitsOptions = Record<string, any>,
  EE erweitert Zeichenfolge = Zeichenfolge
>(
  Optionen: ComponentOptionsWithArrayProps<
    Requisitennamen,
    RawBindings,...>
): DefineComponent<
  Schreibgeschützt<{ [key in PropNames]?: any }>,
  RawBindings,...>

Bildbeschreibung hier einfügen

4: Objektformat mit Objekteigenschaftendeklaration

// Überladung 4: Objektformat mit Objekteigenschaftendeklaration
// siehe „ExtractPropTypes“ in ./componentProps.ts
Exportfunktion defineComponent<
  // die Readonly-Einschränkung erlaubt TS, den Typ von { required: true } zu behandeln
  // als Konstante statt als Boolean.
  PropsOptions erweitert Readonly<ComponentPropsOptions>,
  Rohbindungen,
  D,
  C erweitert ComputedOptions = {},
  M erweitert MethodOptions = {},
  Mixin erweitert ComponentOptionsMixin = ComponentOptionsMixin,
  Erweitert erweitert ComponentOptionsMixin = ComponentOptionsMixin,
  E erweitert EmitsOptions = Record<string, any>,
  EE erweitert Zeichenfolge = Zeichenfolge
>(
  Optionen: ComponentOptionsWithObjectProps<
    PropsOptions, RawBindings, D, C, M, Mixin, Erweitert, E, EE>
): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, E, EE>

Bildbeschreibung hier einfügen

Entwicklungspraxis

Abgesehen von der grundlegenden Verwendung in Unit-Tests gibt es bei der folgenden ParentDialog-Komponente einige Punkte zu beachten:

So schreiben Sie benutzerdefinierte Komponenten und globale Komponenten

Typbeschränkungen für Inject, Ref usw.

So schreiben Sie das Setup und das entsprechende H-Injektionsproblem

So schreiben Sie V-Modell und ScopedSlots in TSX

ParentDialog.vue

<script lang="tsx">
importiere { noop, trim } von „lodash“;
importieren {
  injizieren, Ref, Komponente definieren, aktuelleInstanz abrufen, ref
} von '@vue/composition-api';
Filter aus „@/filters“ importieren;
importiere CommonDialog aus „@/components/CommonDialog“;
importiere ChildTable, { getEmptyModelRow } aus './ChildTable.vue';
 
Schnittstelle IParentDialog exportieren {
  anzeigen: Boolesch;
  specFn: (component_id: HostComponent['id']) => Promise<{ data: DictSpecs }>;
}
 
exportiere StandarddefineComponent<IParentDialog>({
  // Benutzerdefinierte Komponenten in tsx müssen noch Komponenten registrieren: {
    Kindertabelle
  },
  Requisiten: {
    zeigen: {
      Typ: Boolean,
      Standard: false
    },
    Spezifikationsfunktion: {
      Typ: Funktion,
      Standard: noop
    }
  },
 
  // Hinweis: Beim Setup muss die Pfeilfunktion setup: (props, context) => { verwendet werden.
 
    // Beheben Sie das Problem, dass die Funktion „h“ nicht automatisch in tsx eingefügt werden kann // eslint-disable-next-line no-unused-vars
    const h = getCurrentInstance()!.$createElement;
 
    const { emit } = Kontext;
    const { specFn, anzeigen } = Requisiten;
 
    // Verwendung des Filters const { withColon } = filters;
 
    // Inject-Verwendung const pageType = inject<CompSpecType>('pageType', 'foo');
    const dictComponents = inject<Ref<DictComp[]>>('dictComponents', ref([]));
    
    // Ref-Typbeschränkung const dictSpecs = ref<DictSpecs>([]);
    const laden = ref(false);
 
    const _lookupSpecs = async (component_id: HostComponent['id']) => {
      wird geladen.Wert = wahr;
      versuchen {
        const json = warte auf specFn(Komponenten-ID);
        dictSpecs.Wert = json.data;
      Endlich
        wird geladen.Wert = falsch;
      }
    };
 
    const formdata = ref<Spezifikation>({
      Komponenten-ID: '',
      specs_id: '',
      Modell: [getEmptyModelRow()]
    });
    const err1 = ref('');
    const err2 = ref('');
    
    const _doCheck = () => {
      err1.Wert = '';
      err2.Wert = '';
      
      const { Komponenten-ID, Spezifikations-ID, Modell } = Formulardaten.Wert;
      wenn (!Komponenten-ID) {
        err1.value = „Bitte wählen Sie eine Komponente aus“;
        gibt false zurück;
      }
      für (lass i = 0; i < Modell.Länge; i++) {
        const { Marken-ID, Daten } = Modell[i];
        wenn (!brand_id) {
          err2.value = „Bitte wählen Sie eine Marke aus“;
          gibt false zurück;
        }
        Wenn (
          formdata.value.model.some(
            (m, midx) => midx !== i && String(m.Marken-ID) === String(Marken-ID)
          )
        ) {
          err2.value = 'Markenduplikat';
          gibt false zurück;
        }
      }
      gibt true zurück;
    };
 
    const onClose = () => {
      emittieren('update:show', false);
    };
    const onSubmit = async () => {
      const bool = _doCheck();
      wenn (!bool) zurückgeben;
      const params = formdata.value;
      emittieren('senden', Parameter);
      beimSchließen();
    };
 
    // Hinweis: In TSX müssen global registrierte Komponenten wie Element-UI weiterhin das Kebab-Case-Format verwenden????‍
    return () => (
      <CommonDialog
        Klasse="Komp"
        Titel="Neu"
        Breite="1000px"
        labelCancel="Abbrechen"
        labelSubmit="OK"
        vLaden={Ladewert}
        anzeigen={anzeigen}
        beimSchließen={beimSchließen}
        beim Senden = {beim Senden}
      >
        <el-form labelWidth="140px" class="Seite erstellen">
         <el-form-item label={withColon('Komponententyp')} erforderlich={true} Fehler={err1.value}>
            <el-Auswahl
              Klasse="volle Breite"
              Modell={{
                Wert: formdata.value.component_id,
                Rückruf: (v: Zeichenfolge) => {
                  formdata.value.component_id = v;
                  _lookupSpecs(v);
                }
              }}
            >
              {dictComponents.value.map((dictComp: DictComp) => (
                <el-option key={dictComp.id} label={dictComp.component_name} value={dictComp.id} />
              ))}
            </el-Auswahl>
          </el-form-item>
          {formdata.value.komponenten_id ? (
              <el-form-item labelWidth="0" label="" erforderlich={true} Fehler={err2.value}>
                <untergeordnete Tabelle
                  Liste={formdata.value.model}
                  beiÄnderung={(v: Spec['model']) => {
                    formdata.value.model = v;
                  }}
                  beiFehler={(err: string) => {
                    err3.Wert = Fehler;
                  }}
                  scopedSlots={{
                      Standard: (Umfang: beliebig) => (
                        <p>{ Umfang.foo }</p>
                      )
                  }}
                />
              </el-form-item>
          ) : null}
        </el-form>
      </CommonDialog>
    );
  }
});
</Skript>
 
<style lang="scss" scoped>
</Stil>

Zusammenfassung

  • defineComponent() wurde eingeführt, um Parametertypen von setup()-Komponenten korrekt abzuleiten
  • defineComponent kann sich korrekt an Formen wie keine Props, Array-Props usw. anpassen.
  • defineComponent kann eine explizite benutzerdefinierte Props-Schnittstelle akzeptieren oder automatisch aus einem Eigenschaftsvalidierungsobjekt abgeleitet werden
  • In TSX müssen global registrierte Komponenten wie Element-UI weiterhin das Kebab-Case-Format verwenden.
  • In tsx sollte v-model model={ verwenden. {Wert, Rückruf}} Syntax
  • In tsx sollten Slots mit Gültigkeitsbereich scopedSlots={ verwenden. { foo: (Bereich) => () }} Syntax
  • defineComponent gilt nicht für funktionale Komponenten, verwenden Sie stattdessen RenderContext

Dies ist das Ende dieses Artikels über die Rolle von Vue3 defineComponent. Weitere Informationen zur Rolle von Vue3 defineComponent finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Überlegen Sie, ob Vue3 standardmäßig alle OnSomething-Ereignisse als V-On-Ereignisse bindet.
  • Dieser Artikel zeigt Ihnen, wie Sie Vue 3.0 responsive verwenden
  • Implementierung der schnellen Projektkonstruktion von vue3.0+vant3.0
  • Verwenden Sie Vue3, um eine Komponente zu implementieren, die mit js aufgerufen werden kann
  • Detaillierte Erläuterung des zugrunde liegenden Prinzips von defineCustomElement, hinzugefügt in vue3.2
  • Vue3 Vue-Ereignisbehandlungshandbuch

<<:  Verwenden einer MySQL-Datenbank im Docker, um LAN-Zugriff zu erhalten

>>:  Grafisches Tutorial zur Installation und Konfiguration von MySQL 8.0.18

Artikel empfehlen

Grundlegende Ideen zum Auffinden von Fehlern in der Web-Frontend-Entwicklung

Die WEB-Entwicklung besteht hauptsächlich aus zwe...

HTML realisiert Hotel-Screening-Funktion über Formular

<!doctype html> <html xmlns="http:/...

Über IE8-Kompatibilität: Erklärung des X-UA-Compatible-Attributs

Problembeschreibung: Code kopieren Der Code laute...

MySQL mit Nutzungsanalyse

Verwendung von „haben“ Mit der Having-Klausel kön...

Vue3 setup() - Erweiterte Verwendungsbeispiele - ausführliche Erklärung

Inhaltsverzeichnis 1. Unterschiede zwischen Optio...

Ausführliche Erklärung dieses Schlüsselworts in JavaScript

Inhaltsverzeichnis 1. Einleitung 2. Verstehen Sie...

Schritte zum Bereitstellen eines Docker-Projekts in IDEA

Mittlerweile werden die meisten Projekte auf Dock...

Analyse der Prinzipien der MySQL Slow Query-bezogenen Parameter

MySQL Slow Query, dessen vollständiger Name „Slow...