React & BEM - offizielle Zusammenarbeit. Historischer Teil

Hier ist die Geschichte der Integration der BEM-Methodik in das React-Universum. Das Material, das Sie lesen werden, basiert auf der Erfahrung von Yandex-Entwicklern, die den grĂ¶ĂŸten und am meisten ausgelasteten Service in Russland entwickelt haben - Yandex.Search. Wir hatten noch nie so ausfĂŒhrlich und tief darĂŒber gesprochen, warum wir das taten und nicht anders, was uns motivierte und was wir wirklich wollten. Der Außenseiter erhielt auf Konferenzen Trockenveröffentlichungen und Bewertungen. Nur am Rande konnte man so etwas hören. Als Co-Autor war ich empört ĂŒber den Mangel an Informationen außerhalb jedes Mal, wenn ich ĂŒber neue Versionen von Bibliotheken sprach. Aber dieses Mal werden wir alle Details teilen.



Jeder hat von der BEM-Methodik gehört. CSS-Selektoren mit Unterstrichen. Der besprochene Komponentenansatz berĂŒcksichtigt die Art und Weise, wie CSS-CSS-Selektoren geschrieben werden. Aber es wird kein Wort ĂŒber CSS in dem Artikel geben. Nur JS, nur Hardcore!


Um zu verstehen, warum die Methodik erschien und mit welchen Problemen Yandex damals konfrontiert war, empfehle ich Ihnen , sich mit der Geschichte von BEM vertraut zu machen .


Prolog


BEM wurde wirklich als Rettung aus starker KonnektivitĂ€t und Verschachtelung in CSS geboren. Die Aufteilung des style.css Blattes in Dateien fĂŒr jeden Block, jedes Element oder jeden Modifikator fĂŒhrte jedoch zwangslĂ€ufig zu einer Ă€hnlichen Strukturierung des JavaScript-Codes.


Im Jahr 2011 erwarb Open Source die ersten Commits des i-bem.js , das in Verbindung mit bem-xjst Template-Engine bem-xjst . Beide Technologien sind aus XSLT hervorgegangen und dienten der damals beliebten Idee, GeschĂ€ftslogik und KomponentenprĂ€sentation zu trennen. In der Außenwelt waren dies die großartigen Zeiten von Lenker und Unterstrich.


bem-xjst ist eine andere Art von Template-Engine. Um mein Wissen ĂŒber die Architektur von StandardisierungsansĂ€tzen zu erweitern, empfehle ich den Bericht von Sergei Berezhnoy . bem-xjst können die bem-xjst Vorlagen-Engine in der Online-Sandbox ausprobieren.


Aufgrund der Besonderheiten der Yandex-Suchdienste werden BenutzeroberflĂ€chen mithilfe von Daten erstellt. Die Suchergebnisseite ist fĂŒr jede Abfrage eindeutig.



Suchanfrage nach Link



Suchanfrage nach Link



Suchanfrage nach Link


Wenn sich die Unterteilung in einen Block, ein Element und einen Modifikator auf das Dateisystem ausbreitete, konnte so viel wie möglich nur der erforderliche Code fĂŒr jede Seite fĂŒr jede Benutzeranforderung gesammelt werden. Aber wie?


 src/components ├── ComponentName │ ├── _modName │ │ ├── ComponentName_modName.tsx —   │ │ └── ComponentName_modName_modVal.tsx —    │ ├── ElementName │ │ └── ComponentName-ElementName.tsx —   ComponentName │ ├── ComponentName.i18n —   │ │ ├── ru.ts —     │ │ ├── en.ts —     │ │ └── index.ts —    │ ├── ComponentName.test —   │ │ ├── ComponentName.page-object.js — Page Object │ │ ├── ComponentName.hermione.js —   │ │ └── ComponentName.test.tsx — unit- │ ├── ComponentName.tsx —    │ ├── ComponentName.scss —   │ ├── ComponentName.examples.tsx —    Storybook │ └── README.md —   

Moderne Komponentenverzeichnisstruktur


Wie in einigen anderen Unternehmen sind in Yandex Schnittstellenentwickler fĂŒr das Frontend verantwortlich, das aus dem Client-Teil im Browser und dem Server-Teil auf Node.js Der Serverteil verarbeitet die Daten der "großen" Suche und legt ihnen Vorlagen auf. Die primĂ€re Datenverarbeitung konvertiert JSON in BEMJSON , die Datenstruktur fĂŒr bem-xjst Template-Engine. Die Vorlagen-Engine umgeht jeden Knoten des Baums und legt ihm eine Vorlage auf. Da die primĂ€re Konvertierung auf dem Server stattfindet und die Knoten aufgrund der Aufteilung in kleine EntitĂ€ten den Dateien entsprechen, wird bei der Vorlagengenerierung der Browsercode gepusht, der nur auf der aktuellen Seite verwendet wird.


Unten finden Sie die Entsprechung von BEMJSON-Knoten zu Dateien im Dateisystem.


 module.exports = { block: 'Select', elem: 'Item', elemMods: { type: 'navigation' } }; 

 src/components ├── Select │ ├── Item │ │ _type │ │ ├── Select-Item_type_navigation.js │ │ └── Select-Item_type_navigation.css 

Das modulare System von YModules war fĂŒr die Isolierung der Komponenten des JavaScript-Codes im Browser verantwortlich. Sie können damit Module synchron und asynchron an den Browser senden. Ein Beispiel fĂŒr die Funktionsweise von Komponenten mit YModules und i-bem.js finden Sie hier . FĂŒr die meisten Entwickler tun dies heute das webpack und der unveröffentlichte Standard fĂŒr dynamische Importe .


Eine Reihe von BEM-Methoden, eine deklarative Template-Engine und ein JS-Framework mit einem modularen System ermöglichten die Lösung jedes Problems. Im Laufe der Zeit hat sich die Dynamik der BenutzeroberflÀchen jedoch verbessert.


Neue Hoffnung


Im Jahr 2013 verzauberte React die Open Source. TatsÀchlich hat Facebook bereits 2011 damit begonnen. James Long sagt in seinen Notizen von der JS Conf US- Konferenz:


Die letzten beiden Sitzungen waren eine Überraschung. Der erste wurde von zwei Facebook-Entwicklern gegeben und sie kĂŒndigten Facebook React an . Ich habe nicht viele Notizen gemacht, weil ich schockiert war, wie schlecht eine Idee ist, die ich denke. Im Wesentlichen haben sie eine Sprache namens JSX erstellt, mit der Sie XML in JavaScript einbetten können, um reaktive Live-BenutzeroberflĂ€chen zu erstellen. XML In JavaScript.

React hat den Ansatz zum Entwerfen von Webanwendungen geÀndert. Es ist so populÀr geworden, dass Sie heute keinen Entwickler finden können, der noch nichts von React gehört hat. Aber noch etwas ist wichtig: Anwendungen sind anders geworden, SPA ist in unser Leben getreten.


Es ist allgemein anerkannt, dass Yandex-Entwickler einen besonderen Sinn fĂŒr Schönheit in Bezug auf Technologie haben. Manchmal seltsam, was schwer zu diskutieren ist, aber niemals ohne Grund. Als React auf GitHub Sterne gewann, bestanden viele, die mit Yandex-Webtechnologien vertraut waren: Facebook gewann, ließ Ihr Handwerk fallen und schrieb alles auf React neu, bevor es zu spĂ€t war. Es ist wichtig, zwei Dinge zu verstehen.


Erstens gab es keinen Krieg. Unternehmen konkurrieren nicht darum, die besten Rahmenbedingungen der Welt zu schaffen. Wenn ein Unternehmen weniger Zeit (Lesegeld) fĂŒr Infrastrukturaufgaben mit gleicher ProduktivitĂ€t verbringt, profitieren alle davon. Es macht keinen Sinn, Frameworks zu schreiben, um Frameworks zu schreiben. Die besten Entwickler erstellen Tools, die die Aufgaben des Unternehmens optimal lösen. Unternehmen, Dienstleistungen, Ziele - alles ist anders. Daher die Vielfalt der Werkzeuge.


Zweitens suchten wir nach einer Möglichkeit, React so zu verwenden, wie wir es gerne hÀtten. Mit all den Funktionen, die unsere oben beschriebenen Technologien bieten.


Es wird allgemein angenommen, dass Code, der React verwendet, standardmĂ€ĂŸig schnell ist. Wenn Sie das auch denken, dann irren Sie sich zutiefst. Das einzige, was React tut, ist in den meisten FĂ€llen die optimale Interaktion mit dem DOM.


Bis zur Version 16 hatte React einen schwerwiegenden Fehler. Es war 10 mal langsamer als bem-xjst auf dem Server. Wir konnten uns solche AbfĂ€lle nicht leisten. Die Reaktionszeit fĂŒr Yandex ist eine der wichtigsten MessgrĂ¶ĂŸen. Stellen Sie sich vor, wenn Sie nach einem GlĂŒhweinrezept fragen, erhalten Sie eine zehnmal langsamere Antwort als gewöhnlich. Sie werden mit Ausreden nicht zufrieden sein, selbst wenn Sie etwas ĂŒber Webentwicklung wissen. Was können wir ĂŒber die ErklĂ€rung sagen, wie "aber es ist fĂŒr Entwickler bequemer geworden, mit dem DOM zu kommunizieren". FĂŒgen Sie hier das VerhĂ€ltnis von Implementierungspreis und Gewinn hinzu - und Sie selbst treffen die einzig richtige Entscheidung.


Zum GlĂŒck sind die Entwickler seltsame Leute. Wenn etwas nicht funktioniert, ist dies kein Grund, alles fallen zu lassen ...


Auf den Kopf gestellt


Wir waren zuversichtlich, die Langsamkeit von React besiegen zu können. Wir haben bereits eine schnelle Template-Engine. Alles, was Sie brauchen, ist, HTML auf dem Server mit bem-xjst zu generieren und auf dem Client React zu "erzwingen", dieses Markup als sein eigenes zu akzeptieren. Die Idee war so einfach, dass nichts auf einen Misserfolg hindeutete.


In Versionen bis einschließlich 15 hat React die GĂŒltigkeit des Markups mithilfe einer Hash-Summe ĂŒberprĂŒft - einem Algorithmus, der jede Optimierung in einen KĂŒrbis verwandelt. Um React von der GĂŒltigkeit des Markups zu ĂŒberzeugen, musste fĂŒr jeden Knoten eine ID angegeben und die Hash-Summe aller Knoten berechnet werden. Es bedeutete auch, zwei Vorlagen zu unterstĂŒtzen: Reagieren Sie fĂŒr den Client und bem-xjst fĂŒr den Server. Einfache Geschwindigkeitstests mit ID-Installation machten deutlich, dass es keinen Sinn machte, fortzufahren.


Die bem- bem-xjst ist ein sehr unterschĂ€tztes Tool. Schauen Sie sich den Bericht des Hauptbetreuers von Glory Oliyanchuk an und ĂŒberzeugen Sie sich selbst. bem-xjst basiert auf einer Architektur, mit der Sie eine Vorlagensyntax fĂŒr verschiedene Transformationen des bem-xjst verwenden können. Sehr Ă€hnlich zu React, nicht wahr? Mit dieser Funktion können heute Tools wie react-sketchapp .


bem-xjst enthÀlt bem-xjst zwei Arten von Konvertierungen: in HTML und in JSON. Jeder ausreichend sorgfÀltige Entwickler kann seine eigene Engine schreiben, um Vorlagen in alles umzuwandeln. Wir haben bem-xjst einen bem-xjst in eine Folge von Aufrufen von HyperScript-Funktionen umzuwandeln . Dies bedeutete vollstÀndige KompatibilitÀt mit React und anderen Implementierungen des Virtual DOM-Algorithmus, z. B. Preact .



Eine detaillierte EinfĂŒhrung in die Generierung von HyperScript-Funktionsaufrufen


Da React-Vorlagen das Nebeneinander von Layout und GeschĂ€ftslogik erfordern, mussten wir die Logik von i-bem.js in unsere Vorlagen i-bem.js , die dafĂŒr nicht vorgesehen waren. FĂŒr sie war es unnatĂŒrlich. Sie gingen anders. Übrigens!


Unten sehen Sie ein Beispiel aus den Tiefen des Verklebens verschiedener Welten in einer Laufzeit.


 block('select').elem('menu')( def()(function() { const React = require('react'); const Menu = require('../components/menu/menu'); const MenuItem = require('../components/menu-item/menu-item'); const _select = this.ctx._select; const selectComponent = _select._select; return React.createElement.apply(React, [ Menu, { mix: { block : this.block, elem : this.elem }, ref: menu => selectComponent._menu = menu, size: _select.mods.size, disabled: _select.mods.disabled, mode: _select.mods.mode, content: _select.options, checkedItems: _select.bindings.checkedItems, style: _select.bindings.popupMenuWidth, onKeyDown: _select.bindings.onKeyDown, theme: _select.mods.theme, }].concat(_select.options.map(option => React.createElement( MenuItem, { onClick: _select.bindings.onOptionCheck, theme: _select.mods.theme, val: option.value, }, option.content) )) ); }) ); 

NatĂŒrlich hatten wir unsere eigene Versammlung. Wie Sie wissen, ist die schnellste Operation die Verkettung von Zeichenfolgen. Der bem-xjst Motor wurde darauf gebaut, die Baugruppe wurde darauf gebaut. Dateien mit Blöcken, Elementen und Modifikatoren lagen in Ordnern, und die Baugruppe musste die Dateien nur in der richtigen Reihenfolge kleben. Mit diesem Ansatz können Sie JS, CSS und Vorlagen sowie die EntitĂ€ten selbst parallel kleben. Das heißt, wenn Sie vier Komponenten in einem Projekt haben, vier Kerne auf dem Laptop und die Montage einer Komponententechnologie eine Sekunde dauert, dauert das Erstellen des Projekts zwei Sekunden. Hier soll klarer werden, wie wir es schaffen, nur den notwendigen Code in den Browser zu pushen.


All dies hat fĂŒr uns ENB getan . Wir haben den endgĂŒltigen Baum zur Standardisierung nur zur Laufzeit erhalten, und da die AbhĂ€ngigkeit zwischen den Komponenten etwas frĂŒher auftreten musste, um BĂŒndel zu sammeln, wurde diese Funktion von der wenig bekannten deps.js Technologie ĂŒbernommen. Sie konnten ein AbhĂ€ngigkeitsdiagramm zwischen Komponenten erstellen, wonach der Kollektor den Code in der gewĂŒnschten Reihenfolge unter Umgehung des Diagramms kleben konnte.


React Version 16 funktioniert in dieser Richtung nicht mehr. Die AusfĂŒhrungsgeschwindigkeit der Vorlagen auf dem Server war gleich . In ProduktionsstĂ€tten wurde der Unterschied nicht mehr wahrnehmbar.


Knoten: v8.4.0
Kinder: 5K


Renderermittlere Zeitops / sek
predct v8.2.666,235 ms15
bem-xjst v8.8.471,326 ms14
reagiere v16.1.073,966 ms14

Über die folgenden Links können Sie den Verlauf des Ansatzes wiederherstellen:



Haben wir noch etwas versucht?




Motivation


In der Mitte der Geschichte wird es nĂŒtzlich sein, darĂŒber zu sprechen, was uns motiviert hat. Es hat sich am Anfang gelohnt, aber - wer erinnert sich an das alte, dieses Auge als Geschenk. Warum brauchen wir das alles? Was kann BEM bringen, was React nicht kann? Fragen, die fast jeder stellt.


Zersetzung


Die FunktionalitĂ€t der Komponenten wird von Jahr zu Jahr komplizierter und die Anzahl der Variationen nimmt zu. Dies wird durch if oder switch Konstruktionen ausgedrĂŒckt, wodurch die Codebasis zwangslĂ€ufig wĂ€chst, wodurch das Gewicht der Komponente und des Projekts, das eine solche Komponente verwendet, zunimmt. Der Hauptteil der Logik der React-Komponente ist in der render() -Methode enthalten. Um die FunktionalitĂ€t einer Komponente zu Ă€ndern, muss der grĂ¶ĂŸte Teil der Methode neu geschrieben werden, was zwangslĂ€ufig zu einer exponentiellen Zunahme der Anzahl hochspezialisierter Komponenten fĂŒhrt.


Jeder kennt die Bibliotheken Material-UI , Fabric-UI und React-Bootstrap . Im Allgemeinen haben alle bekannten Bibliotheken mit Komponenten den gleichen Nachteil. Stellen Sie sich vor, Sie haben mehrere Projekte und alle verwenden dieselbe Bibliothek. Sie nehmen die gleichen Komponenten, aber in verschiedenen Variationen: Hier gibt es Auswahlmöglichkeiten mit KontrollkĂ€stchen, es gibt keine, es gibt blaue SchaltflĂ€chen mit einem Symbol, es gibt rote SchaltflĂ€chen ohne. Das Gewicht von CSS und JS, das die Bibliothek Ihnen bietet, ist in allen Projekten gleich. Aber warum? Variationen von Komponenten sind in die Komponente selbst eingebettet und werden mitgeliefert, ob Sie es möchten oder nicht. FĂŒr uns ist das inakzeptabel.


Yandex hat auch eine eigene Bibliothek mit Komponenten - Lego. Es wird in ~ 200 Diensten angewendet. Möchten wir, dass die Verwendung von Lego in Search fĂŒr Yandex.Health gleich viel kostet? Sie kennen die Antwort.


PlattformĂŒbergreifende Entwicklung


Um mehrere Plattformen zu unterstĂŒtzen, erstellen sie meistens entweder eine separate Version fĂŒr jede Plattform oder eine adaptive.


Die Entwicklung einzelner Versionen erfordert zusĂ€tzliche Ressourcen: Je mehr Plattformen, desto mehr Aufwand. Das Beibehalten des synchronen Zustands der Produkteigenschaften in verschiedenen Versionen fĂŒhrt zu neuen Schwierigkeiten.


Die Entwicklung einer adaptiven Version verkompliziert den Code, erhöht das Gewicht und verringert die Geschwindigkeit des Produkts mit dem richtigen Unterschied zwischen den Plattformen.


Wollen wir, dass unsere Eltern / Freunde / Kollegen / Kinder Desktop-Versionen auf MobilgerÀten mit geringerer Internetgeschwindigkeit und geringerer ProduktivitÀt verwenden? Sie kennen die Antwort.


Die Experimente


Wenn Sie Projekte fĂŒr ein großes Publikum entwickeln, mĂŒssen Sie sich jeder Änderung sicher sein. A / B-Experimente sind eine Möglichkeit, dieses Vertrauen zu gewinnen.


Möglichkeiten, Code fĂŒr Experimente zu organisieren:


  • Projektgabel und Erstellung von Service-Instanzen in der Produktion;
  • Punktbedingungen innerhalb der Codebasis.

Wenn das Projekt viele langwierige Experimente umfasst, verursacht das Verzweigen der Codebasis erhebliche Kosten. Es ist notwendig, jeden Zweig mit dem Experiment auf dem neuesten Stand zu halten: Port-korrigierte Fehler und ProduktfunktionalitĂ€t. Die Codebasis-Verzweigung erschwert das Überschneiden von Experimenten mehrmals.


Die Punktbedingungen funktionieren flexibler, erschweren jedoch die Codebasis: Die Bedingungen des Experiments können verschiedene Teile des Projekts beeinflussen. Eine große Anzahl von Bedingungen beeintrĂ€chtigt die Leistung, indem die Codemenge fĂŒr den Browser erhöht wird. Es ist notwendig, die Bedingungen zu entfernen, den Code grundlegend zu machen oder das fehlgeschlagene Experiment vollstĂ€ndig zu löschen.


In Search ~ 100 Online-Experimente in verschiedenen Kombinationen fĂŒr unterschiedliche Zielgruppen. Sie konnten es selbst sehen. Denken Sie daran, vielleicht haben Sie die FunktionalitĂ€t bemerkt und eine Woche spĂ€ter ist sie auf magische Weise verschwunden. Wollen wir Produkttheorien testen, um Hunderte von Zweigen der aktiven Codebasis von 500.000 Zeilen zu verwalten, die tĂ€glich von ~ 60 Entwicklern geĂ€ndert werden? Sie kennen die Antwort.


Globaler Wandel


Sie können beispielsweise eine von Button geerbte CustomButton Komponente aus einer Bibliothek erstellen. Der geerbte CustomButton jedoch nicht fĂŒr alle Komponenten aus der Bibliothek, die Button . Eine Bibliothek verfĂŒgt möglicherweise ĂŒber eine Search , die aus Input und Button . In diesem Fall wird der geerbte CustomButton nicht in der CustomButton . Wollen wir die gesamte Codebasis, in der Button verwendet wird, manuell umgehen?



Langer Weg zur Komposition


Wir haben beschlossen, die Strategie zu Àndern. Im vorherigen Ansatz haben sie die Yandex-Technologie als Grundlage genommen und versucht, React dazu zu bringen, auf dieser Basis zu arbeiten. Neue Taktiken deuteten auf das Gegenteil hin. So entstand das bem-react-core- Projekt.


Hör auf! Warum ĂŒberhaupt reagieren?

Wir sahen darin die Möglichkeit, explizites anfĂ€ngliches Rendern in HTML und die manuelle UnterstĂŒtzung des Status der JS-Komponente spĂ€ter in der Laufzeit zu beseitigen - tatsĂ€chlich wurde es möglich, BEMHMTL-Vorlagen und JS-Komponenten in einer Technologie zusammenzufĂŒhren.


v1.0.0


ZunĂ€chst wollten wir alle Best Practices und Eigenschaften bem-xjst zu React in die Bibliothek ĂŒbertragen. Das erste, was auffĂ€llt, ist die Signatur oder, wenn Sie es vorziehen, die Syntax zur Beschreibung der Komponenten.


Was hast du getan, da ist JSX!


Die erste Version wurde auf der Grundlage der Vererbung erstellt - einer Bibliothek, mit deren Hilfe Klassen und Vererbung implementiert werden können. Wie einige von Ihnen sich erinnern, hatten Prototyp-Prototypen in JavaScript damals keine Klassen, es gab kein super . Im Allgemeinen fehlen sie noch, genauer gesagt, dies sind nicht die Klassen, die zuerst in den Sinn kommen. inherit hat alles getan, was Klassen im ES2015-Standard jetzt können, und was als schwarze Magie gilt: Mehrfachvererbung und ZusammenfĂŒhrung von Prototypen, anstatt die Kette neu aufzubauen, was sich positiv auf die Leistung auswirkt. Sie werden sich nicht irren, wenn Sie der Meinung sind, dass es wie Erben in Node.js sinnvoll erscheint, aber sie funktionieren anders.


Unten finden Sie ein Beispiel fĂŒr die Syntax der Vorlagen bem-react-core@v1.0.0 .


App-Header.js


 import { decl } from 'bem-react-core'; export default decl({ block: 'App', elem: 'Header', attrs: { role: 'heading' }, content() { return ' '; } }); 

App-Header@desktop.js


 import { decl } from 'bem-react-core'; export default decl({ block: 'App', elem: 'Header', tag: 'h1', attrs() { return { ...this.__base(...arguments), 'aria-level': 1 }, }, content() { return ` ${this.__base(...arguments)}     h1`; } }); 

App-Header@touch.js


 import { decl } from 'bem-react-core'; export default decl({ block: 'App', elem: 'Header', tag: 'h2', content() { return ` ${this.__base(...arguments)}  `; } }); 

index.js


 import ReactDomServer from 'react-dom/server'; import AppHeader from 'b:App e:Header'; ReactDomServer.renderToStaticMarkup(<AppHeader />); 

output@desktop.html


 <h1 class="App-Header" role="heading" aria-level="1">A       h1</h2> 

output@touch.html


 <h2 class="App-Header" role="heading">   </h2> 

Die GerĂ€tevorlagen fĂŒr komplexere Komponenten finden Sie hier .


Da eine Klasse ein Objekt ist und die Arbeit mit Objekten in JavaScript am bequemsten ist, ist die Syntax angemessen. Die Syntax wurde spÀter zu ihrem Mastermind bem-xjst .


Die Bibliothek war ein globales Repository fĂŒr Objektdeklarationen - die Ergebnisse der AusfĂŒhrung der Deklarationsfunktion, Teile von EntitĂ€ten: ein Block, ein Element oder ein Modifikator. BEM bietet einen eindeutigen Namensmechanismus und eignet sich daher zum Erstellen von SchlĂŒsseln in einem Tresor. Die resultierende React-Komponente wurde an ihrem Verwendungsort geklebt. Der Trick ist, dass die decl beim Importieren des Moduls funktioniert hat. Auf diese Weise konnte anhand einer einfachen Liste von Importen angegeben werden, welche Teile der Komponente an den jeweiligen Stellen benötigt werden. Aber denken Sie daran: Die Komponenten sind komplex, es gibt viele Teile, die Liste der Importe ist lang, die Entwickler sind faul.


Magie importieren


Wie Sie sehen können, gibt es in den Codebeispielen Zeilen, import AppHeader from 'b:App e:Header' .


Du hast den Standard gebrochen! Es ist unmöglich! Es wird einfach nicht funktionieren!


Erstens arbeitet der Importstandard nicht mit Begriffen im Sinne von „Es muss einen Pfad zu einem echten Modul in der Importlinie geben“. Zweitens ist es syntaktischer Zucker, der mit Babel umgewandelt wurde. Drittens, seltsame import txt from 'raw-loader!./file.txt'; Interpunktionskonstrukte fĂŒr den Webpack- import txt from 'raw-loader!./file.txt'; aus irgendeinem Grund haben sie niemanden gestört.
Unser Block wird also auf zwei Plattformen prÀsentiert: desktop , touch .


 import Hello from 'b:Hello'; //     : var Hello = [ require('path/to/desktop/Hello/Hello.js'), require('path/to/touch/Hello/Hello.js') ][0].applyDecls(); 

Hello , applyDecls , inherit , React-.


Babel, , . webpack, , .


, :


  • , , ;
  • ;
  • React- .

:


  • TypeScript/Flow;
  • React- ;
  • - ;
  • .

v2.0.0


bem-react-core@v1.0.0 , .


 import { Elem } from 'bem-react-core'; import { Button } from '../Button'; export class AppHeader extends Elem { block = 'App'; elem = 'Header'; tag() { return 'h2'; } content() { return ( <Button> </Button> ); } } 

, . , , TypeScript/Flow. , inherit «» , , .


:
— webpack Babel;
— ;
— , .


HOC , .


 import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { Block, Elem, withMods } from 'bem-react-core'; interface IButtonProps { children: string; } interface IModsProps extends IButtonProps { type: 'link' | 'button'; } //   Text class Text extends Elem { block = 'Button'; elem = 'Text'; tag() { return 'span'; } } //   Button class Button<T extends IModsProps> extends Block<T> { block = 'Button'; tag() { return 'button'; } mods() { return { type: this.props.type }; } content() { return ( <Text>{this.props.children}</Text> ); } } //    Button,    type   link class ButtonLink extends Button<IModsProps> { static mod = ({ type }: any) => type === 'link'; tag() { return 'a'; } mods() { return { type: this.props.type }; } attrs() { return { href: 'www.yandex.ru' }; } } //   Button  ButtonLink const ButtonView = withMods(Button, ButtonLink); ReactDOM.render( <React.Fragment> <ButtonView type='button'>Click me</ButtonView> <ButtonView type='link'>Click me</ButtonView> </React.Fragment>, document.getElementById('root') ); 

, .


withMods , (), . , , withMods , . . , , , ( ) . . , , — , .


, :


  • . , . , TS. , . ES5 TS super , . , TS , .
  • . TS ES6 Babel ES5. , npm- . , Babel.

:


  • , . , . : DOM-. HOC, . withMods .
  • (, , ) . SFC .
  • CSS-. CSS- JS- . , , .

v2.



, . . , , 1 2. .


— . CSS- HOC, — dependency injection .


React:


  • CSS-.
  • (, );

. . React.ComponentType -. HOC compose .


.


dependency injection, React.ContextAPI . , , . , . DI — HOC, . . , , .


, , . , , 4 , 1.5Kb .


. Vielen Dank an diejenigen, die bis zum Ende gelesen haben. , React . .

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


All Articles