Erfahrung der Rambler Group: Wie wir damit begannen, die Bildung und das Verhalten von Front-End-React-Komponenten vollständig zu kontrollieren


Es gibt viele Möglichkeiten, eine moderne Webanwendung zu erstellen, aber jedes Team steht unweigerlich vor denselben Fragen: Wie verteilt man die Verantwortlichkeiten für Vorder- und Rückseite, wie minimiert man das Auftreten doppelter Logik - zum Beispiel bei der Validierung von Daten, welche Bibliotheken für die Arbeit verwendet werden sollen, wie man Zuverlässigkeit gewährleistet und transparenter Transport zwischen Vorder- und Rückseite und Dokumentation des Codes.

Unserer Meinung nach ist es uns gelungen, ein gutes Beispiel für eine in Komplexität und Gewinn ausgewogene Lösung zu implementieren, die wir erfolgreich in der Produktion auf der Basis von Symfony und React einsetzen.

Welche Art von Datenaustauschformat können wir wählen, wenn wir die Entwicklung der Backend-API in einem aktiv entwickelten Webprodukt planen, das dynamische Formulare mit verwandten Feldern und komplexer Geschäftslogik enthält?

  • SWAGGER ist eine gute Option, es gibt Dokumentation und praktische Debugging-Tools. Darüber hinaus gibt es Bibliotheken für Symfony, die den Prozess automatisieren. Leider hat sich das JSON-Schema als vorzuziehen erwiesen.
  • JSON-Schema - Diese Option wurde von Front-End-Entwicklern angeboten. Sie hatten bereits Bibliotheken, in denen sie Formulare anzeigen konnten. Dies bestimmte unsere Wahl. Mit dem Format können Sie die primitiven Überprüfungen beschreiben, die im Browser durchgeführt werden können. Es gibt auch eine Dokumentation, die alle möglichen Optionen für das Schema beschreibt.
  • GraphQL ist ziemlich jung. Nicht so viele serverseitige und Frontend-Bibliotheken. Zum Zeitpunkt der Erstellung des Systems wurde dies in Zukunft nicht berücksichtigt. Der beste Weg, eine API zu erstellen, wird in einem separaten Artikel dazu veröffentlicht.
  • SOAP - hat eine strikte Typisierung von Daten, die Fähigkeit, Dokumentation zu erstellen, aber es ist nicht so einfach, sich mit der React-Front anzufreunden. SOAP hat auch einen höheren Overhead für dieselbe nutzbare Menge übertragener Daten.

Alle diese Formate deckten unsere Bedürfnisse nicht vollständig ab, so dass ich meinen eigenen Harvester schreiben musste. Ein ähnlicher Ansatz kann hochwirksame Lösungen für eine bestimmte Anwendung bieten, birgt jedoch Risiken:

  • hohe Wahrscheinlichkeit von Fehlern;
  • oft nicht 100% Dokumentation und Testabdeckung;
  • geringe "Modularität" aufgrund der Schließung der Software-API. In der Regel werden solche Lösungen unter einem Monolithen geschrieben und implizieren keine gemeinsame Nutzung zwischen Projekten in Form von Komponenten, da dies eine spezielle architektonische Konstruktion erfordert (lesen Sie die Entwicklungskosten).
  • hohes Einstiegsniveau neuer Entwickler. Es kann lange dauern, bis man die Kühle eines Fahrrads verstanden hat.

Daher empfiehlt es sich, nach der Regel gängige und stabile Bibliotheken (wie das linke Pad von npm) zu verwenden. Der beste Code ist der, den Sie nie geschrieben, aber das Geschäftsproblem gelöst haben. Die Entwicklung des Webanwendungs-Backends in den Werbetechnologien der Rambler Group wird bei Symfony durchgeführt. Wir werden nicht auf alle verwendeten Komponenten des Frameworks eingehen, sondern im Folgenden auf den Hauptteil eingehen, auf dessen Grundlage die Arbeit implementiert wird - das Symfony-Formular . Das Frontend verwendet React und die entsprechende Bibliothek, die das JSON-Schema für WEB-Besonderheiten erweitert - React JSON Schema Form .

Allgemeines Arbeitsschema:



Dieser Ansatz hat viele Vorteile:

  • Die Dokumentation wird sofort generiert, ebenso wie die Möglichkeit, automatische Tests zu erstellen - wiederum gemäß dem Schema.
  • Alle übertragenen Daten werden eingegeben.
  • Es ist möglich, Informationen über die grundlegenden Validierungsregeln zu übertragen.
    Schnelle Integration der Transportschicht in React - dank der Mozilla React JSON-Schemabibliothek;
  • die Fähigkeit, Front-End-Webkomponenten aus der Box durch Bootstrap-Integration zu generieren;
  • Die logische Gruppierung, eine Reihe von Validierungen und möglichen Werten von HTML-Elementen sowie die gesamte Geschäftslogik werden an einem einzigen Punkt gesteuert. Im Backend gibt es keine Duplizierung von Code.
  • Es ist so einfach wie möglich, die Anwendung auf andere Plattformen zu portieren. Der Ansichtsteil ist vom Steuerelement getrennt (siehe vorherigen Absatz). Anstelle von React und dem Browser kann die Android- oder iOS-Anwendung Benutzeranforderungen rendern und verarbeiten.

Schauen wir uns die Komponenten und das Schema ihrer Interaktion genauer an.

Mit JSON Schema können Sie zunächst primitive Überprüfungen beschreiben, die auf dem Client durchgeführt werden können, z. B. das Binden oder Eingeben verschiedener Teile des Schemas:

const schema = { "title": "A registration form", "description": "A simple form example.", "type": "object", "required": [ "firstName", "lastName" ], "properties": { "firstName": { "type": "string", "title": "First name" }, "lastName": { "type": "string", "title": "Last name" }, "password": { "type": "string", "title": "Password", "minLength": 3 }, "telephone": { "type": "string", "title": "Telephone", "minLength": 10 } } } 

Für die Arbeit mit Front-End-Schemata gibt es die beliebte Bibliothek React JSON Schema Form , die die für JSON Schema für die Webentwicklung erforderlichen Add-Ons bereitstellt:

uiSchema - Das JSON-Schema selbst bestimmt die Art der zu übergebenden Parameter. Dies reicht jedoch nicht aus, um eine Webanwendung zu erstellen. Beispielsweise kann ein Feld vom Typ String als <Eingabe ... /> oder als <Textbereich ... /> dargestellt werden. Dies sind wichtige Nuancen, die berücksichtigen, dass Sie ein Diagramm für den Client korrekt zeichnen müssen. UiSchema dient auch dazu, diese Nuancen zu vermitteln. Beispielsweise können Sie für das oben dargestellte JSON-Schema die visuelle Webkomponente des folgenden uiSchema angeben:

 const uiSchema = { "firstName": { "ui:autofocus": true, "ui:emptyValue": "" }, "age": { "ui:widget": "updown", "ui:title": "Age of person", "ui:description": "(earthian year)" }, "bio": { "ui:widget": "textarea" }, "password": { "ui:widget": "password", "ui:help": "Hint: Make it strong!" }, "date": { "ui:widget": "alt-datetime" }, "telephone": { "ui:options": { "inputType": "tel" } } } 

Ein Beispiel für einen Live-Spielplatz finden Sie hier .

Mit dieser Verwendung des Schemas wird das Front-End-Rendering von den Standard-Bootstrap-Komponenten in mehreren Zeilen implementiert:

 render(( <Form schema={schema} uiSchema={uiSchema} /> ), document.getElementById("app")); 

Wenn die mit Bootstrap gelieferten Standard-Widgets nicht zu Ihnen passen und Sie eine Anpassung benötigen, können Sie für einige Datentypen Ihre eigenen Vorlagen in uiSchema angeben. Zum Zeitpunkt des Schreibens werden Zeichenfolge , Zahl , Ganzzahl und Boolescher Wert unterstützt.

FormData - enthält Formulardaten, zum Beispiel:

 { "firstName": "Chuck", "lastName": "Norris", "age": 78, "bio": "Roundhouse kicking asses since 1940", "password": "noneed" } 

Nach dem Rendern werden die Widgets mit diesen Daten gefüllt - nützlich zum Bearbeiten von Formularen sowie für einige benutzerdefinierte Mechanismen, die wir für verwandte Felder und komplexe Formulare hinzugefügt haben, mehr dazu weiter unten.

In den oben beschriebenen Abschnitten auf der Plugin-Seite erfahren Sie mehr über alle Nuancen beim Einrichten und Verwenden der Abschnitte.

Standardmäßig können Sie in der Bibliothek nur mit diesen drei Abschnitten arbeiten. Für eine vollwertige Webanwendung müssen Sie jedoch eine Reihe von Funktionen hinzufügen:

Fehler - Es ist auch erforderlich, Fehler verschiedener Backend-Prüfungen zum Rendern an den Benutzer übertragen zu können, und Fehler können entweder einfache Validierungsfehler sein - zum Beispiel die Eindeutigkeit der Anmeldung bei der Registrierung des Benutzers oder komplexere Fehler basierend auf der Geschäftslogik - d. H. Wir müssen in der Lage sein, ihre (Fehler-) Anzahl und Texte der angezeigten Benachrichtigungen anzupassen. Zu diesem Zweck wurde zusätzlich zu den oben beschriebenen der Abschnitt Fehler zum Satz der übertragenen Daten hinzugefügt. Für jedes Feld wird hier eine Liste der Fehler für das Rendern definiert

Aktion , Methode - Zum Senden der vom Benutzer vorbereiteten Daten an das Backend wurden zwei Attribute hinzugefügt, die die URL des Backends des Controllers, der die Verarbeitung durchführt, und die HTTP-Übermittlungsmethode enthalten

Als Ergebnis haben wir für die Kommunikation zwischen Vorder- und Rückseite json mit den folgenden Abschnitten erhalten:

 { "action": "https://...", "method": "POST", "errors":{}, "schema":{}, "formData":{}, "uiSchema":{} } 

Aber wie werden diese Daten im Backend generiert? Zum Zeitpunkt der Erstellung des Systems gab es keine vorgefertigten Bibliotheken, mit denen Sie Symfony Form in ein JSON-Schema konvertieren konnten. Jetzt sind sie bereits erschienen, haben aber ihre Nachteile - zum Beispiel interpretiert das LiformBundle das JSON-Schema ziemlich frei und ändert den Standard nach eigenem Ermessen, so dass ich leider meine eigene Implementierung schreiben musste.

Als Grundlage für die Generierung wird das Standard- Symfony-Formular verwendet . Es reicht aus, den Builder zu verwenden und die erforderlichen Felder hinzuzufügen:
Formularbeispiel
 $builder ->add('title', TextType::class, [ 'label' => 'label.title', 'attr' => [ 'title' => 'title.title', ], ]) ->add('description', TextareaType::class, [ 'label' => 'label.description', 'attr' => [ 'title' => 'title.description', ], ]) ->add('year', ChoiceType::class, [ 'choices' => range(1981, 1990), 'choice_label' => function ($val) { return $val; }, 'label' => 'label.year', 'attr' => [ 'title' => 'title.year', ], ]) ->add('genre', ChoiceType::class, [ 'choices' => [ 'fantasy', 'thriller', 'comedy', ], 'choice_label' => function ($val) { return 'genre.choice.'.$val; }, 'label' => 'label.genre', 'attr' => [ 'title' => 'title.genre', ], ]) ->add('available', CheckboxType::class, [ 'label' => 'label.available', 'attr' => [ 'title' => 'title.available', ], ]); 


Am Ausgang wird diese Form in eine Schaltung der Form umgewandelt:
JsonSchema-Beispiel
 { "action": "//localhost/create.json", "method": "POST", "schema": { "properties": { "title": { "maxLength": 255, "minLength": 1, "type": "string", "title": "label.title" }, "description": { "type": "string", "title": "label.description" }, "year": { "enum": [ "1981", "1982", "1983", "1984", "1985", "1986", "1987", "1988", "1989", "1990" ], "enumNames": [ "1981", "1982", "1983", "1984", "1985", "1986", "1987", "1988", "1989", "1990" ], "type": "string", "title": "label.year" }, "genre": { "enum": [ "fantasy", "thriller", "comedy" ], "enumNames": [ "genre.choice.fantasy", "genre.choice.thriller", "genre.choice.comedy" ], "type": "string", "title": "label.genre" }, "available": { "type": "object", "title": "label.available" } }, "required": [ "title", "description", "year", "genre", "available" ], "type": "object" }, "formData": { "title": "", "description": "", "year": "", "genre": "" }, "uiSchema": { "title": { "ui:help": "title.title", "ui:widget": "text" }, "description": { "ui:help": "title.description", "ui:widget": "textarea" }, "year": { "ui:widget": "select", "ui:help": "title.year" }, "genre": { "ui:widget": "select", "ui:help": "title.genre" }, "available": { "ui:help": "title.available", "ui:widget": "checkbox" }, "ui:widget": "mainForm" } } 


Der gesamte Code, der Formulare in JSON konvertiert, ist geschlossen und wird nur in der Rambler-Gruppe verwendet. Wenn die Community Interesse an diesem Thema hat, werden wir ihn im Bundle-Format in unserem Github-Repository umgestalten .

Schauen wir uns einige weitere Aspekte an, ohne die es schwierig ist, eine moderne Webanwendung zu erstellen:

Feldvalidierung


Die Einstellung erfolgt mit dem Symfony-Validator , der die Regeln für die Validierung eines Objekts beschreibt. Ein Beispiel für einen Validator:

 <property name="title"> <constraint name="Length"> <option name="min">1</option> <option name="max">255</option> <option name="minMessage">title.min</option> <option name="maxMessage">title.max</option> </constraint> <constraint name="NotBlank"> <option name="message">title.not_blank</option> </constraint> </property> 


In diesem Beispiel ändert eine Einschränkung vom Typ NotBlank das Schema, indem dem Feld der erforderlichen Felder des Schemas ein Feld hinzugefügt wird, und eine Einschränkung vom Typ Länge fügt die Attribute Schema-> Eigenschaften-> Titel-> maxLength und Schema-> Eigenschaften-> Titel-> minLength hinzu, die bei der Validierung bereits berücksichtigt werden sollten am vorderen Ende.

Elemente gruppieren


Im wirklichen Leben sind einfache Formen eher eine Ausnahme von der Regel. Zum Beispiel kann ein Projekt ein Formular mit einer großen Anzahl von Feldern haben und es ist nicht die beste Option, alles in einer soliden Liste anzugeben - wir müssen uns um die Benutzer unserer Anwendung kümmern:

Die offensichtliche Entscheidung besteht darin, das Formular in logische Gruppen von Steuerelementen zu unterteilen, damit der Benutzer leichter navigieren und weniger Fehler machen kann:

Wie Sie wissen, sind die Funktionen des sofort einsatzbereiten Symfony-Formulars recht umfangreich. Beispielsweise können Formulare von anderen Formularen geerbt werden. Dies ist praktisch, in unserem Fall gibt es jedoch Nachteile. In der aktuellen Implementierung bestimmt die Reihenfolge im JSON-Schema die Reihenfolge, in der das Formularelement im Browser gezeichnet wird. Die Vererbung kann gegen diese Reihenfolge verstoßen. Eine Möglichkeit bestand darin, Elemente zu gruppieren, zum Beispiel:

Beispiel für eine verschachtelte Form
 $info = $builder ->create('info',FormType::class,['inherit_data'=>true]) ->add('title', TextType::class, [ 'label' => 'label.title', 'attr' => [ 'title' => 'title.title', ], ]) ->add('description', TextareaType::class, [ 'label' => 'label.description', 'attr' => [ 'title' => 'title.description', ], ]); $builder ->add($info) ->add('year', ChoiceType::class, [ 'choices' => range(1981, 1990), 'choice_label' => function ($val) { return $val; }, 'label' => 'label.year', 'attr' => [ 'title' => 'title.year', ], ]) ->add('genre', ChoiceType::class, [ 'choices' => [ 'fantasy', 'thriller', 'comedy', ], 'choice_label' => function ($val) { return 'genre.choice.'.$val; }, 'label' => 'label.genre', 'attr' => [ 'title' => 'title.genre', ], ]) ->add('available', CheckboxType::class, [ 'label' => 'label.available', 'attr' => [ 'title' => 'title.available', ], ]); 


Dieses Formular wird in eine Schaltung des Formulars umgewandelt:

Beispiel für ein verschachteltes JsonSchema
 "schema": { "properties": { "info": { "properties": { "title": { "type": "string", "title": "label.title" }, "description": { "type": "string", "title": "label.description" } }, "required": [ "title", "description" ], "type": "object" }, "year": { "enum": [ "1981", "1982", "1983", "1984", "1985", "1986", "1987", "1988", "1989", "1990" ], "enumNames": [ "1981", "1982", "1983", "1984", "1985", "1986", "1987", "1988", "1989", "1990" ], "type": "string", "title": "label.year" }, "genre": { "enum": [ "fantasy", "thriller", "comedy" ], "enumNames": [ "genre.choice.fantasy", "genre.choice.thriller", "genre.choice.comedy" ], "type": "string", "title": "label.genre" }, "available": { "type": "object", "title": "label.available" } }, "required": [ "info", "year", "genre", "available" ], "type": "object" } 


und entsprechendes uiSchema
 "uiSchema": { "info": { "title": { "ui:help": "title.title", "ui:widget": "text" }, "description": { "ui:help": "title.description", "ui:widget": "textarea" }, "ui:widget": "form" }, "year": { "ui:widget": "select", "ui:help": "title.year" }, "genre": { "ui:widget": "select", "ui:help": "title.genre" }, "available": { "ui:help": "title.available", "ui:widget": "checkbox" }, "ui:widget": "group" } 


Diese Gruppierungsmethode passte nicht zu uns, da das Formular für die Daten von der Präsentation abhängt und beispielsweise nicht in der API oder anderen Formularen verwendet werden kann. Es wurde beschlossen, zusätzliche Parameter in uiSchema zu verwenden, ohne den aktuellen JSON-Schema-Standard zu verletzen. Infolgedessen wurden dem Symphonieformular zusätzliche Optionen des folgenden Typs hinzugefügt:

 'fieldset' => [ 'groups' => [ [ 'type' => 'base', 'name' => 'info', 'fields' => ['title', 'description'], 'order' => ['title', 'description'] ] ], 'type' => 'base' ] 

Dies wird in das folgende Schema konvertiert:

 "ui:group": { "type": "base", "groups": [ { "type": "group", "name": "info", "title": "legend.info", "fields": [ "title", "description" ], "order": [ "title", "description" ] } ], "order": [ "info" ] }, 


Vollversion von Schema und uiSchema
 "schema": { "properties": { "title": { "maxLength": 255, "minLength": 1, "type": "string", "title": "label.title" }, "description": { "type": "string", "title": "label.description" }, "year": { "enum": [ "1989", "1990" ], "enumNames": [ "1989", "1990" ], "type": "string", "title": "label.year" }, "genre": { "enum": [ "fantasy", "thriller", "comedy" ], "enumNames": [ "genre.choice.fantasy", "genre.choice.thriller", "genre.choice.comedy" ], "type": "string", "title": "label.genre" }, "available": { "type": "boolean", "title": "label.available" } }, "required": [ "title", "description", "year", "genre", "available" ], "type": "object" } 

 "uiSchema": { "title": { "ui:help": "title.title", "ui:widget": "text" }, "description": { "ui:help": "title.description", "ui:widget": "textarea" }, "year": { "ui:widget": "select", "ui:help": "title.year" }, "genre": { "ui:widget": "select", "ui:help": "title.genre" }, "available": { "ui:help": "title.available", "ui:widget": "checkbox" }, "ui:group": { "type": "base", "groups": [ { "type": "group", "name": "info", "title": "legend.info", "fields": [ "title", "description" ], "order": [ "title", "description" ] } ], "order": [ "info" ] }, "ui:widget": "fieldset" } 


Da die von uns verwendete React-Bibliothek auf der Front-End-Seite dies nicht sofort unterstützt, musste ich diese Funktionalität selbst hinzufügen. Durch das Hinzufügen eines neuen Elements „ui: group“ erhalten wir die Möglichkeit, den Prozess der Gruppierung von Elementen und Formularen mithilfe der aktuellen API vollständig zu steuern.

Dynamische Formen


Was ist, wenn ein Feld von einem anderen abhängt? Eine Dropdown-Liste mit Unterkategorien hängt beispielsweise von der ausgewählten Kategorie ab.



Symfony FORM bietet uns die Möglichkeit, mithilfe von Ereignissen dynamische Formulare zu erstellen. Leider wurde diese Funktion zum Zeitpunkt der Implementierung von JSON Schema nicht unterstützt, obwohl diese Funktion in neueren Versionen verfügbar war. Ursprünglich bestand die Idee darin, die gesamte Liste einem Enum- und EnumNames-Objekt zuzuweisen, basierend darauf, welche Werte gefiltert werden sollen:

 { "properties": { "genre": { "enum": [ "fantasy", "thriller", "comedy" ], "enumNames": [ "genre.choice.fantasy", "genre.choice.thriller", "genre.choice.comedy" ], "type": "string", "title": "label.genre" }, "sgenre": { "enum": [ "eccentric", "romantic", "grotesque" ], "enumNames": [ { "title": "sgenre.choice.eccentric", "genre": "comedy" }, { "title": "sgenre.choice.romantic", "genre": "comedy" }, { "title": "sgenre.choice.grotesque", "genre": "comedy" } ], "type": "string", "title": "label.genre" } }, "type": "object" } 

Bei diesem Ansatz ist es jedoch erforderlich, für jedes dieser Elemente eine eigene Verarbeitung in das Front-End zu schreiben, ganz zu schweigen von der Tatsache, dass alles sehr kompliziert wird, wenn mehrere dieser Objekte vorhanden sind oder ein Element von mehreren Listen abhängt. Darüber hinaus nimmt die an das Frontend gesendete Datenmenge für die korrekte Verarbeitung und Darstellung aller Abhängigkeiten erheblich zu. Stellen Sie sich zum Beispiel eine Zeichnung eines Formulars vor, das aus drei miteinander verbundenen Feldern besteht - Ländern, Städten, Straßen. Die Menge an Anfangsdaten, die an das Backend an das Frontend gesendet werden muss, kann Thin Clients verärgern, und wie Sie sich erinnern, müssen wir uns um unsere Benutzer kümmern. Daher wurde beschlossen, die Dynamik durch Hinzufügen benutzerdefinierter Attribute zu implementieren:

  • SchemaID - Ein Attribut des Schemas, enthält die Adresse des Controllers zum Verarbeiten der aktuell eingegebenen FormData und zum Aktualisieren des Schemas des aktuellen Formulars, falls dies von der Geschäftslogik gefordert wird.
  • Neu laden - Ein Attribut, das dem Frontend mitteilt, dass eine Änderung in diesem Feld eine Aktualisierung der Schaltung durch Senden von Formulardaten an das Backend initiiert.

Das Vorhandensein einer SchemaID mag wie eine Duplizierung erscheinen - schließlich gibt es ein Aktionsattribut , aber hier geht es um die Aufteilung der Verantwortung - der SchemaID- Controller ist für die Zwischenaktualisierung des Schemas und des UISchema verantwortlich , und der Aktionscontroller führt die erforderliche Geschäftsaktion aus - erstellt oder aktualisiert beispielsweise ein Objekt und lässt nicht zu, dass ein Teil des Formulars als gesendet wird erzeugt Validierungsprüfungen. Mit diesen Ergänzungen sieht das Schema folgendermaßen aus:

 { "schemaId": "//localhost/schema.json", "properties": { "genre": { "enum": [ "fantasy", "thriller", "comedy" ], "enumNames": [ "genre.choice.fantasy", "genre.choice.thriller", "genre.choice.comedy" ], "type": "string", "title": "label.genre" }, "sgenre": { "enum": [], "enumNames": [], "type": "string", "title": "label.sgenre" } }, "uiSchema": { "genre": { "ui:options": { "reload": true }, "ui:widget": "select", "ui:help": "title.genre" }, "sgenre": { "ui:widget": "select", "ui:help": "title.sgenre" }, "ui:widget": "mainForm" }, "type": "object" } 

Wenn Sie das Feld "Genre" ändern, sendet das Frontend das gesamte Formular mit den aktuellen Daten an das Backend und erhält als Antwort eine Reihe von Abschnitten, die zum Rendern des Formulars erforderlich sind:

 { action: “https://...”, method: "POST", schema:{} formData:{} uiSchema:{} } 

und rendern anstelle des aktuellen Formulars. Was sich nach dem Senden genau ändert, hängt von der Rückseite ab, die Zusammensetzung oder Anzahl der Felder kann sich ändern usw. - jede Änderung, die die Geschäftslogik der Anwendung erfordert.

Fazit


Aufgrund einer kleinen Erweiterung des Standardansatzes haben wir eine Reihe zusätzlicher Funktionen erhalten, mit denen wir die Bildung und das Verhalten von Front-End-React-Komponenten vollständig steuern, dynamische Schaltkreise auf der Grundlage der Geschäftslogik erstellen, einen einzigen Punkt für die Bildung von Validierungsregeln festlegen und schnell und flexibel neue VIEW-Teile erstellen können - beispielsweise für Mobilgeräte oder Desktops Anwendungen. Wenn Sie in solch kühne Experimente einsteigen, müssen Sie sich an den Standard erinnern, auf dessen Grundlage Sie arbeiten, und die Abwärtskompatibilität mit ihm aufrechterhalten. Anstelle von React kann jede andere Bibliothek im Frontend verwendet werden. Hauptsache, Sie schreiben einen Transportadapter in das JSON-Schema und verbinden eine Formular-Rendering-Bibliothek. Bootstrap hat mit React gut funktioniert, da wir Erfahrung mit diesem Technologie-Stack hatten, aber der Ansatz, über den wir gesprochen haben, schränkt Sie bei der Auswahl der Technologien nicht ein. Anstelle von Symfony kann es auch ein anderes Framework geben, mit dem Sie Formulare in das JSON-Schema-Format konvertieren können.

Update: Sie können unseren Bericht über Symfony Moscow Meetup # 14 darüber ab 1:15:00 Uhr sehen.

Source: https://habr.com/ru/post/de417023/


All Articles