VorwortEs ist lange her, seit wir uns das letzte Mal getroffen haben, meine Freunde. Ich bin erst vor Kurzem in eine neue Firma eingestiegen und mein Terminkalender ist sehr voll. Normalerweise habe ich keine Zeit, Artikel zu schreiben, daher wird die Aktualisierungsfrequenz geringer. Mir war am Wochenende zu Hause langweilig, und plötzlich kam mein jüngerer Bruder zu mir und bat mich dringend um Hilfe. Er sagte, dass ihm die Gegenpartei bei seinem Vorstellungsgespräch bei Tencent ein rekursives Menü in Vue gegeben und ihn gebeten hatte, es umzusetzen, also kam er zur Überprüfung zu mir zurück. Es ist nun einmal so, dass diese Woche eine kurze Woche ist, sodass ich nicht ausgehen und spielen möchte, also bleibe ich einfach zu Hause und schreibe etwas Code. Ich habe mir die Anforderungen angesehen und festgestellt, dass sie tatsächlich ziemlich kompliziert sind und die Verwendung rekursiver Komponenten erfordern. Ich möchte diese Gelegenheit nutzen, um einen Artikel über die Implementierung rekursiver Komponenten mit Vue3 + TS zusammenzufassen. brauchenSie können den Effekt zunächst auf den Github-Seiten in der Vorschau anzeigen. Die Anforderung besteht darin, dass das Backend ein Menü mit potenziell unendlichen Ebenen im folgenden Format zurückgibt: [ { ID: 1, Vater-ID: 0, Status: 1, Name: „Life Science-Wettbewerb“, _Kind: [ { ID: 2, Vater-ID: 1, Status: 1, Name: 'Feldübung', _child: [{ id: 3, father_id: 2, status: 1, name: 'Botanik' }], }, { Ich würde: 7, Vater-ID: 1, Status: 1, Name: „Wissenschaftliche Forschung“, _Kind: [ { id: 8, father_id: 7, status: 1, name: 'Botanik und Pflanzenphysiologie' }, { id: 9, father_id: 7, status: 1, name: 'Zoologie und Tierphysiologie' }, { id: 10, father_id: 7, status: 1, name: 'Mikrobiologie' }, { id: 11, father_id: 7, status: 1, name: 'Ökologie' }, ], }, { id: 71, father_id: 1, status: 1, name: 'Hinzufügen' }, ], }, { Ich würde: 56, Vater-ID: 0, Status: 1, Name: 'Zugehörig zur Aufnahmeprüfung für das Graduiertenstudium', _Kind: [ { id: 57, father_id: 56, status: 1, name: 'Politik' }, { id: 58, father_id: 56, status: 1, name: 'Fremdsprache' }, ], }, ] 1. Wenn die Menüelemente jeder Ebene das Attribut _child haben, werden alle Untermenüs dieses Elements weiterhin angezeigt, nachdem dieses Menü ausgewählt wurde. Vorschau des animierten Bildes: 2. Wenn Sie auf eine beliebige Ebene klicken, müssen Sie den vollständigen ID-Link des Menüs an die äußerste Ebene übergeben, um Daten von der übergeordneten Komponente anzufordern. Sie klicken beispielsweise auf die Kategorie „Wissenschaftliche Forschung“. Bei der Emission nach außen ist es auch notwendig, die ID des ersten Untermenüs „Botanik und Pflanzenphysiologie“ und die ID des übergeordneten Menüs „Life Science Competition“ anzugeben, d. h. [1, 7, 8]. 3. Der Stil jeder Ebene kann angepasst werden. erreichenDies ist offensichtlich eine Voraussetzung für eine rekursive Komponente. Beim Entwurf einer rekursiven Komponente müssen wir zunächst genau über die Zuordnung von Daten zu Ansichten nachdenken. In den vom Backend zurückgegebenen Daten kann jede Ebene des Arrays einem Menüelement entsprechen, sodass die Ebene des Arrays einer Zeile in der Ansicht entspricht. Im Menü der aktuellen Ebene wird das untergeordnete Element des angeklickten und ausgewählten Menüs als Untermenüdaten verwendet und an die rekursive NestMenu-Komponente übergeben, bis das hervorgehobene Menü einer bestimmten Ebene kein untergeordnetes Element mehr hat und die Rekursion beendet wird. Da die Anforderungen erfordern, dass der Stil jeder Ebene unterschiedlich sein kann, müssen wir bei jedem Aufruf der rekursiven Komponente eine Tiefe abrufen, die die Ebene aus den Eigenschaften der übergeordneten Komponente darstellt, und diese Tiefe + 1 an die rekursive NestMenu-Komponente übergeben. Dies sind die wesentlichen Punkte, anschließend erfolgt die Codierungsimplementierung. Schauen wir uns zunächst die allgemeine Struktur des Vorlagenteils der NestMenu-Komponente an: <Vorlage> <div Klasse="wrap"> <div Klasse="Menü-Wrap"> <div Klasse="Menüpunkt" v-for="Menüelement in Daten" >{{menuItem.name}}</div> </div> <Nest-Menü :Schlüssel="activeId" :data="Untermenü" :Tiefe="Tiefe + 1" ></nest-menu> </div> </Vorlage> Wie erwartet stellt „menu-wrap“ die aktuelle Menüebene dar und „nest-menu“ ist die Komponente selbst, die für die rekursive Darstellung von Unterkomponenten verantwortlich ist. Erstes RendernWenn wir zum ersten Mal die Daten für das gesamte Menü abrufen, müssen wir das ausgewählte Element jeder Menüebene standardmäßig auf das erste Untermenü setzen. Da dies wahrscheinlich asynchron erfolgt, ist es am besten, diese Daten zu beobachten, um diesen Vorgang auszuführen. // Wenn sich die Datenquelle des Menüs ändert, wird standardmäßig das erste Element der aktuellen Ebene ausgewählt const activeId = ref<number | null>(null) betrachten( () => Eigenschaften.Daten, (neueDaten) => { wenn (!activeId.value) { wenn (neueDaten && neueDaten.Länge) { activeId.Wert = neueDaten[0].id } } }, { sofort: wahr, } ) Beginnen wir nun von oben. Die ActiveId der ersten Ebene wird auf die ID des Life-Science-Wettbewerbs gesetzt. Beachten Sie, dass die Daten, die wir an die rekursive untergeordnete Komponente übergeben, d. h. an das untergeordnete Element des Life-Science-Wettbewerbs, über subMenu abgerufen werden, das eine berechnete Eigenschaft ist: const getActiveSubMenu = () => { returniere Daten.find(({ id }) => id === activeId.value)._child } const subMenu = berechnet(getActiveSubMenu) Auf diese Weise werden die untergeordneten Elemente des Life-Science-Wettbewerbs abgerufen und als Daten der Unterkomponente weitergegeben. Klicken Sie auf den MenüpunktZurück zum vorherigen Anforderungsdesign: Nach dem Klicken auf das Menüelement muss, unabhängig davon, auf welche Ebene geklickt wird, der vollständige ID-Link über Emit an die äußerste Ebene übergeben werden. Daher müssen wir hier noch einige weitere Verarbeitungen durchführen: /** * Rekursives Sammeln der ID des ersten Elements im Untermenü */ const getSubIds = (Kind) => { const subIds = [] const traverse = (Daten) => { if (data && data.length) { const erste = Daten[0] subIds.push(erste.id) durchqueren(erstes._Kind) } } durchqueren (Kind) SubIDs zurückgeben } const onMenuItemClick = (Menüelement) => { const newActiveId = menuItem.id wenn (neueActiveId !== activeId.value) { activeId.value = neueActiveId const child = getActiveSubMenu() const subIds = getSubIds(Kind) // Verketten Sie die Standard-IDs der ersten Elemente des Untermenüs und senden Sie sie an die übergeordnete Komponente. Kontext.emit('ändern', [newActiveId, ...subIds]) } } Da die Regel, die wir zuvor festgelegt haben, besagt, dass nach dem Klicken auf das neue Menü standardmäßig das erste Element des Untermenüs ausgewählt wird, suchen wir auch rekursiv nach dem ersten Element in den Untermenüdaten und fügen es in SubIds bis zur untersten Ebene ein. Beachten Sie hier context.emit("change", [newId, ...subIds]);, das das Ereignis nach oben ausgibt. Wenn dieses Menü ein Menü auf mittlerer Ebene ist, dann ist seine übergeordnete Komponente auch NestMenu. Wir müssen auf das Änderungsereignis hören, wenn die NestMenu-Komponente rekursiv auf der übergeordneten Ebene aufgerufen wird. <Nest-Menü :Schlüssel="activeId" v-if="activeId !== null" :data="getActiveSubMenu()" :Tiefe="Tiefe + 1" @change="beiSubActiveIdChange" ></nest-menu> Was soll getan werden, nachdem das übergeordnete Menü das Änderungsereignis des untergeordneten Menüs empfängt? Ja, es muss weiter nach oben weitergegeben werden: const onSubActiveIdChange = (ids) => { Kontext.emit('ändern', [activeId.value].concat(ids)) } Hier müssen Sie einfach Ihre aktuelle ActiveId an den Anfang des Arrays anfügen und sie dann weiter nach oben weitergeben. Wenn also eine Komponente auf einer beliebigen Ebene auf das Menü klickt, wird sie zunächst ihre eigene ActiveId verwenden, um die Standard-ActiveId aller Unterebenen zu spleißen, und sie dann Schicht für Schicht nach oben ausstrahlen. Und jedes übergeordnete Menü oben stellt seine eigene ActiveId voran, genau wie ein Relais. Schließlich können wir den vollständigen ID-Link ganz einfach in der Komponente auf Anwendungsebene abrufen: <Vorlage> <nest-menu :data="Menü" @change="activeIdsChange" /> </Vorlage> Standard exportieren { Methoden: { activeIdsChange(ids) { diese.ids = ids; console.log("Derzeit ausgewählter ID-Pfad", ids); }, }, StilunterscheidungDa wir bei jedem Aufruf einer rekursiven Komponente Tiefe + 1 hinzufügen, können wir eine Stildifferenzierung erreichen, indem wir diese Zahl nach dem Klassennamen einfügen. <Vorlage> <div Klasse="wrap"> <div Klasse = "menu-wrap": Klasse = "menu-wrap-${depth}""> <div class="menu-item">{{menuItem.name}}</div> </div> <Nest-Menü /> </div> </Vorlage> <Stil> .menu-wrap-0 { Hintergrund: #ffccc7; } .menu-wrap-1 { Hintergrund: #fff7e6; } .menu-wrap-2 { Hintergrund: #fcffe6; } </Stil> Standardmäßige HervorhebungNach dem Schreiben des obigen Codes ist es ausreichend, die Anforderungen zu erfüllen, wenn kein Standardwert vorhanden ist. Zu diesem Zeitpunkt sagte der Interviewer, dass das Produkt erfordert, dass diese Komponente standardmäßig hervorgehoben wird, indem eine ID beliebiger Ebene übergeben wird. Tatsächlich ist das für uns nicht schwierig. Wir können den Code leicht ändern. Nehmen wir an, dass wir in der übergeordneten Komponente eine aktive ID über den URL-Parameter oder eine andere Methode erhalten und zuerst alle übergeordneten Elemente dieser ID durch Tiefensuche finden. Konstante ActiveId = 7 const findPath = (Menüs, Ziel-ID) => { Lassen Sie IDs const traverse = (Untermenüs, vorherige) => { wenn (ids) { zurückkehren } wenn (!Untermenüs) { zurückkehren } Untermenüs.fürJedes((Untermenü) => { wenn (Untermenü.id === activeId) { ids = [...vorherige, aktiveId] zurückkehren } durchlaufen(Untermenü._child, [...vorheriges, Untermenü.id]) }) } durchqueren (Menüs, []) Rückgabe-IDs } const ids = findPath(Daten, ActiveId) Hier wähle ich, beim Rekursieren die ID der vorherigen Ebene zu übernehmen, sodass ich nach dem Finden der Ziel-ID das komplette übergeordnete und untergeordnete ID-Array problemlos zusammenfügen kann. Dann übergeben wir die erstellten IDs als ActiveIds an NestMenu. Zu diesem Zeitpunkt muss NestMenu sein Design ändern und zu einer „gesteuerten Komponente“ werden. Sein Rendering-Status wird durch die von unserer äußeren Schicht übergebenen Daten gesteuert. Daher müssen wir beim Initialisieren der Parameter die Wertelogik ändern und „activeIds [Tiefe]“ Priorität einräumen. Beim Klicken auf das Menüelement in der äußersten Seitenkomponente sollten die Daten von „activeIds“ synchron geändert werden, wenn das Änderungsereignis empfangen wird. Auf diese Weise werden die von NestMenu empfangenen Daten nicht verwechselt. <Vorlage> <nest-menu :data="Daten" :defaultActiveIds="ids" @change="activeIdsChange" /> </Vorlage> Wenn NestMenu initialisiert wird, behandelt es die Situation, in der Standardwerte vorhanden sind, und verwendet vorrangig den aus dem Array erhaltenen ID-Wert. setup(Eigenschaften: IProps, Kontext) { const { Tiefe = 0, aktiveIds } = Requisiten; /** * Hier können ActiveIds auch asynchron abgerufen werden. Verwenden Sie daher watch, um die Initialisierung sicherzustellen. */ const activeId = ref<Zahl | null | undefiniert>(null); betrachten( () => aktiveIds, (neueActiveIds) => { wenn (neueActiveIds) { const newActiveId = newActiveIds[Tiefe]; wenn (neueActiveId) { activeId.value = neueActiveId; } } }, { sofort: wahr, } ); } Wenn das ActiveIds-Array auf diese Weise nicht abgerufen werden kann, ist der Standardwert immer noch null. In der Logik zum Beobachten der Änderungen der Menüdaten wird ActiveId, wenn es null ist, auf die ID des ersten Untermenüs initialisiert. betrachten( () => Eigenschaften.Daten, (neueDaten) => { wenn (!activeId.value) { wenn (neueDaten && neueDaten.Länge) { activeId.Wert = neueDaten[0].id } } }, { sofort: wahr, } ) Wenn der äußerste Seitencontainer auf das Änderungsereignis wartet, muss die Datenquelle synchronisiert werden: <Vorlage> <nest-menu :data="Daten" :activeIds="ids" @change="activeIdsChange" /> </Vorlage> <Skript> importiere { ref } von "vue"; Standard exportieren { Name: "App", aufstellen() { const activeIdsChange = (neueIds) => { ids.value = neueIds; }; zurückkehren { Ausweise, activeIdsChange, }; }, }; </Skript> Auf diese Weise kann die Hervorhebungsauswahllogik des gesamten NestMenu gesteuert werden, wenn ActiveIds von außen übergeben werden. Fehler, die durch Änderungen in Datenquellen verursacht werdenZu diesem Zeitpunkt nahm der Interviewer eine kleine Änderung an Ihrer App-Datei vor und demonstrierte einen Fehler wie diesen: Die folgende Logik wird der Setup-Funktion von App.vue hinzugefügt: beimMounted(() => { setzeTimeout(() => { Menü.Wert = [Daten[0]].slice() }, 1000) }) Das heißt, eine Sekunde nach dem Rendern der Komponente ist nur noch ein Element in der äußersten Ebene des Menüs vorhanden. Zu diesem Zeitpunkt klickt der Interviewer innerhalb einer Sekunde auf das zweite Element in der äußersten Ebene. Nachdem sich die Datenquelle geändert hat, meldet diese Komponente einen Fehler: Dies liegt daran, dass sich die Datenquelle geändert hat, der ActiveId-Status innerhalb der Komponente jedoch immer noch auf einer ID festhängt, die nicht mehr existiert. Dies führt dazu, dass die berechnete Eigenschaft des Untermenüs bei der Berechnung fehlschlägt. Wir modifizieren die Logik der Datenquelle für die Beobachtungsdaten geringfügig: betrachten( () => Eigenschaften.Daten, (neueDaten) => { wenn (!activeId.value) { wenn (neueDaten && neueDaten.Länge) { activeId.Wert = neueDaten[0].id } } // Wenn der Wert von `activeId` in den Daten der aktuellen Ebene nicht gefunden werden kann, bedeutet dies, dass dieser Wert ungültig ist. // Passen Sie ihn an die ID des ersten Untermenüelements in der Datenquelle an wenn (!props.data.find(({ id }) => id === activeId.value)) { activeId.value = props.data?.[0].id } }, { sofort: wahr, // Nach der Beobachtung der Datenänderungen synchron ausführen, um Renderfehler zu vermeiden flush: 'sync', } ) Beachten Sie, dass Flush: „Sync“ hier entscheidend ist. Vue3 löst Callbacks aus, nachdem es auf Änderungen in der Datenquelle geachtet hat. Standardmäßig wird es nach dem Post-Rendering ausgeführt. Unter den aktuellen Anforderungen führt es jedoch direkt zu einem Fehler, wenn wir zum Rendern die falsche ActiveId verwenden. Daher müssen wir diese Überwachung manuell in ein synchrones Verhalten umwandeln. Jetzt müssen Sie sich keine Sorgen mehr über Rendering-Fehler machen, die durch Änderungen in den Datenquellen verursacht werden. Vollständiger Code App.vue<Vorlage> <nest-menu :data="Daten" :activeIds="ids" @change="activeIdsChange" /> </Vorlage> <Skript> importiere { ref } von "vue"; importiere NestMenu aus "./components/NestMenu.vue"; Daten aus "./menu.js" importieren; importiere { getSubIds } aus "./util"; Standard exportieren { Name: "App", aufstellen() { // Angenommen, die standardmäßig ausgewählte ID ist 7 Konstante ActiveId = 7; const findPath = (Menüs, Ziel-ID) => { lass IDs; const traverse = (Untermenüs, vorherige) => { wenn (ids) { zurückkehren; } wenn (!Untermenüs) { zurückkehren; } Untermenüs.fürJedes((Untermenü) => { wenn (Untermenü.id === activeId) { ids = [...vorherige, aktiveId]; zurückkehren; } durchqueren(Untermenü._child, [...vorheriges, Untermenü.id]); }); }; durchqueren (Menüs, []); IDs zurückgeben; }; const ids = ref(findPath(data, activeId)); const activeIdsChange = (neueIds) => { ids.value = neueIds; console.log("Derzeit ausgewählter ID-Pfad", newIds); }; zurückkehren { Ausweise, activeIdsChange, Daten, }; }, Komponenten: NestMenü, }, }; </Skript> NestMenu.vue <Vorlage> <div Klasse="wrap"> <div Klasse = "menu-wrap": Klasse = "menu-wrap-${depth}""> <div Klasse="Menüpunkt" v-for="Menüelement in Daten" :Klasse="getActiveClass(menuItem.id)" @click="beimMenüpunktKlick(Menüpunkt)" :Schlüssel="Menüelement.id" >{{menuItem.name}}</div> </div> <Nest-Menü :Schlüssel="activeId" v-if="Untermenü && Untermenü.Länge" :data="Untermenü" :Tiefe="Tiefe + 1" :activeIds="aktiveIds" @change="beiSubActiveIdChange" ></nest-menu> </div> </Vorlage> <script lang="ts"> importiere { watch, ref, onMounted, berechnet } von „vue“; Daten aus "../menu" importieren; Schnittstelle IProps { Daten: Datentyp; Tiefe: Zahl; aktiveIds?: Nummer[]; } Standard exportieren { Name: "NestMenu", Requisiten: ["Daten", "Tiefe", "activeIds"], setup(Eigenschaften: IProps, Kontext) { const { Tiefe = 0, aktive IDs, Daten } = Requisiten; /** * Hier können ActiveIds auch asynchron abgerufen werden. Verwenden Sie daher watch, um die Initialisierung sicherzustellen. */ const activeId = ref<Zahl | null | undefiniert>(null); betrachten( () => aktiveIds, (neueActiveIds) => { wenn (neueActiveIds) { const newActiveId = newActiveIds[Tiefe]; wenn (neueActiveId) { activeId.value = neueActiveId; } } }, { sofort: wahr, leeren: 'synchronisieren' } ); /** * Wenn sich die Menüdatenquelle ändert, wird standardmäßig das erste Element der aktuellen Ebene ausgewählt*/ betrachten( () => Eigenschaften.Daten, (neueDaten) => { wenn (!activeId.value) { wenn (neueDaten && neueDaten.Länge) { activeId.value = neueDaten[0].id; } } // Wenn der Wert von `activeId` in den Daten der aktuellen Ebene nicht gefunden werden kann, bedeutet dies, dass dieser Wert ungültig ist. // Passen Sie ihn an die ID des ersten Untermenüelements in der Datenquelle an wenn (!props.data.find(({ id }) => id === activeId.value)) { activeId.value = props.data?.[0].id; } }, { sofort: wahr, // Nach der Beobachtung der Datenänderungen synchron ausführen, um Renderfehler zu vermeiden flush: "sync", } ); const onMenuItemClick = (Menüelement) => { const newActiveId = menuItem.id; wenn (neueActiveId !== activeId.value) { activeId.value = neueActiveId; const child = getActiveSubMenu(); const subIds = getSubIds(Kind); // Verketten Sie die Standard-IDs der ersten Elemente des Untermenüs und senden Sie sie an die übergeordnete Komponente. Kontext.emit("ändern", [newActiveId, ...subIds]); } }; /** * Beim Empfang der aktualisierten ActiveId der untergeordneten Komponente * muss sie als Vermittler fungieren, um die übergeordnete Komponente darüber zu informieren, dass die ActiveId aktualisiert wurde*/ const onSubActiveIdChange = (ids) => { Kontext.emit("ändern", [activeId.value].concat(ids)); }; const getActiveSubMenu = () => { returniere props.data?.find(({ id }) => id === activeId.value)._child; }; const subMenu = berechnet(getActiveSubMenu); /** * Stilbezogen */ const getActiveClass = (id) => { wenn (id === activeId.value) { returniere "Menü aktiv"; } zurückkehren ""; }; /** * Rekursives Sammeln der ID des ersten Elements im Untermenü */ const getSubIds = (Kind) => { const subIds = []; const traverse = (Daten) => { if (data && data.length) { const erste = Daten[0]; subIds.push(erste.id); durchqueren(erstes._Kind); } }; durchqueren (Kind); SubIds zurückgeben; }; zurückkehren { Tiefe, aktiveID, Untermenü, bei Klick auf Menüelement, bei Änderung der SubActiveId, getActiveClass, }; }, }; </Skript> <Stil> .wickeln { Polsterung: 12px 0; } .menu-wrap { Anzeige: Flex; Flex-Wrap: Umwickeln; } .menu-wrap-0 { Hintergrund: #ffccc7; } .menu-wrap-1 { Hintergrund: #fff7e6; } .menu-wrap-2 { Hintergrund: #fcffe6; } .Menüpunkt { Rand links: 16px; Cursor: Zeiger; Leerzeichen: Nowrap; } .menu-aktiv { Farbe: #f5222d; } </Stil> Quellcodeadresse github.com/sl1673495/v… ZusammenfassenEine rekursive Menükomponente ist einfach, aber auch schwierig. Wenn wir die asynchronen Rendering- und Beobachtungsstrategien von Vue nicht verstehen, können uns die Bugs in der Mitte lange Zeit stören. Daher ist es notwendig, die Prinzipien angemessen zu erlernen. Beim Entwickeln allgemeiner Komponenten müssen Sie auf das Timing der Datenquelleneingabe (synchron, asynchron) achten. Bei asynchron eingegebenen Daten müssen Sie die Watch-API gut nutzen, um Änderungen zu beobachten und entsprechende Vorgänge auszuführen. Bedenken Sie außerdem, ob Änderungen in der Datenquelle zu Konflikten mit dem in der Komponente gespeicherten Originalzustand führen und führen Sie zum entsprechenden Zeitpunkt Bereinigungsvorgänge durch. Es gibt noch eine kleine Frage. Wenn ich mir die Datenquelle der NestMenu-Komponente anschaue, wähle ich Folgendes: beobachten((() => props.data); Anstatt zu dekonstruieren und dann zu beobachten: const { Daten } = Requisiten; beobachten(() => Daten); Gibt es einen Unterschied zwischen diesen beiden? Dies ist eine weitere Interviewfrage, mit der Sie Ihre Fähigkeiten testen. Dies ist das Ende dieses Artikels über die Implementierung rekursiver Menükomponenten mit Vue3+TypeScript. Weitere relevante Inhalte zu rekursiven Menükomponenten von Vue3+TypeScript finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen! Das könnte Sie auch interessieren:
|
<<: Lösen Sie das Problem ungültiger UTF8-Einstellungen in MySQL 5.6
>>: Allgemeines Startskriptbeispiel für ein Linux-Java-Programm
Inhaltsverzeichnis 1. Nachfrage 2. Wirkung 3. All...
Ich werde meinen ersten Versuch mit vue3.0 aufzei...
Vorwort Erfahren Sie, wie Sie auf Ihrem System ei...
In diesem Artikel wird der spezifische JS-Code zu...
Vorwort Dieser Artikel stellt hauptsächlich den r...
Vorwort Was ist die Rolle eines Agenten? - Mehrer...
Wenn der Server während der Entwicklung gestartet...
Basisbild Das Basisbild hat zwei Bedeutungen: Ist...
Die Aktion des Formulars unterscheidet sich vom UR...
PHP-bezogene Pfade in der Ubuntu-Umgebung PHP-Pfa...
Hinweis: Ich verwende Centos, um Docker zu instal...
Hintergrund: Ich möchte einen SAP ECC Server inst...
Dieser Artikel zeichnet das ausführliche Tutorial...
Es gibt zwei Möglichkeiten: 1. Servicemethode Übe...
1. Beschreibung Wenn wir in MySQL die Gesamtzahl ...