Was ist der Unterschied zwischen Reaktionskomponente und Reaktionselement? Die Dokumentation erwähnt beide, geht aber nicht ins Detail. Einige Methoden erfordern Komponenten, andere Elemente ...
Antworten:
Hier gibt es drei verwandte Arten von Dingen mit ihren eigenen Namen:
Dies ist etwas überraschend, da Sie, wenn Sie an andere UI-Frameworks gewöhnt sind, erwarten könnten, dass es nur zwei Arten von Dingen gibt, die ungefähr Klassen (wie Widget) und Instanzen (wie new Widget()) entsprechen. Dies ist in React nicht der Fall. Komponenteninstanzen sind nicht dasselbe wie Elemente, und es besteht auch keine Eins-zu-Eins-Beziehung zwischen ihnen. Betrachten Sie zur Veranschaulichung diesen Code:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
class MyComponent extends React.Component {
constructor(props) {
super(props);
console.log('This is a component instance:', this);
}
render() {
const another_element = <div>Hello, World!</div>;
console.log('This is also an element:', another_element);
return another_element;
}
}
console.log('This is a component:', MyComponent)
const element = <MyComponent/>;
console.log('This is an element:', element);
ReactDOM.render(
element,
document.getElementById('root')
);
Im obigen Code:
MyComponent(die Klasse selbst ) ist eine Komponenteelementist ein Element. Es ist keine Instanz von MyComponent; Vielmehr handelt es sich lediglich um eine Beschreibung der zu erstellenden Komponenteninstanz. Es ist ein Objekt mit key, props, refund typeEigenschaften. Hier keyund refsind null, propsist ein leeres Objekt, und typeist MyComponent.MyComponentwird beim elementRendern erstellt (und protokolliert sich im obigen Beispiel von ihrem Konstruktor) .another_elementist auch ein Element, und hat key, ref, propsund typeEigenschaften wie elementtut - aber diesmal von dem Wert typeist die Zeichenfolge "div".Die Designgründe, warum React diese drei unterschiedlichen Konzepte hat, werden im Blog-Beitrag React Components, Elements and Instances des React-Teams , den ich zum Lesen empfehle, ausführlich untersucht .
Schließlich ist anzumerken, dass in den offiziellen Dokumenten der Begriff "Komponente" für eine Funktion oder Klasse und "Komponenteninstanz" für eine Instanz streng verwendet wird, andere Quellen diese Terminologie jedoch nicht unbedingt einhalten. Sie sollten erwarten, dass "Komponente" (falsch) als "Komponenteninstanz" verwendet wird, wenn Sie Antworten oder Diskussionen zum Stapelüberlauf auf GitHub lesen.
<Child/>von ihrer render()Methode zurückkehrt, wird jedes Mal, wenn sie render()aufgerufen wird, ein neues Element zurückgegeben, aber eine bereits vorhandene ChildKomponente kann wiederverwendet werden, um dies zu realisieren Element.)
el = <SomeComponent>und dieses eine Element dann mehrmals in einen großen JSX-Ausdruck einbetten, der von einer render()Methode zurückgegeben wird (d. H. Do <div>{el}{el}{el}{el}</div>).
Um die Antwort weiter zu erläutern, verfügt ein Reaktionselement über keine Methoden und nichts über den Prototyp. Das macht sie auch schnell.
"Ein ReactElement ist eine leichte, zustandslose, unveränderliche, virtuelle Darstellung eines DOM-Elements" - Glossar der Reaktionsbegriffe
Eine Reaktionskomponentenfunktion render()gibt einen DOM-Baum von Reaktionselementen hinter den Kulissen zurück (dies ist übrigens das virtuelle DOM). Es gibt einige komplexe Mapping- und Diff-Logik, aber im Grunde sind diese React-Elemente den DOM-Elementen zugeordnet.
Sie können ein Element auch direkt erstellen, React.createElement(arg)wobei arg ein HTML-Tag-Name oder eine React Component-Klasse sein kann.
ReactElementder VDOM selbst ist ... aber ich bin kein großer Experte in diesem Thema, das ist nur eine Vermutung. Nach meinem Verständnis muss noch eine Reaktion Elementauf ein VDOM gerendert werden, die sich dann vom "vorherigen" VDOM unterscheidet. Ich denke user6445533, die Antwort sagt dasselbe. Recht ? Ich bin kein Experte, aber irgendwie sagt mir der gesunde Menschenverstand, dass dies nach einigem Nachdenken die einzig sinnvolle Interpretation ist ... aber meine Intuition könnte falsch sein.
Ein React-Element ist nur ein einfaches altes JavaScript Objectohne eigene Methoden. Es hat im Wesentlichen vier Eigenschaften:
type, eine StringDarstellung eines HTML-Tags oder einer Referenz, die sich auf eine Reaktionskomponente beziehtkey, a String, um ein Reaktionselement eindeutig zu identifizierenref, eine Referenz für den Zugriff auf den zugrunde liegenden DOM-Knoten oder die React Component Instance)props(Eigenschaften Object)Ein Reaktionselement ist keine Instanz einer Reaktionskomponente. Es ist nur eine vereinfachte "Beschreibung", wie die typezu erstellende React Component-Instanz (oder abhängig von einem HTML-Tag) aussehen soll.
Ein Reaktionselement, das eine Reaktionskomponente beschreibt, weiß nicht, auf welchen DOM-Knoten sie schließlich gerendert wird. Diese Zuordnung wird abstrahiert und beim Rendern aufgelöst.
Reaktionselemente können untergeordnete Elemente enthalten und können daher Elementbäume bilden, die den virtuellen DOM-Baum darstellen.
Eine benutzerdefinierte Reaktionskomponente wird entweder durch React.createClassoder durch Erweitern React.Component(ES2015) erstellt. Wenn eine Reaktionskomponente instanziiert wird, erwartet sie eine props Objectund gibt eine Instanz zurück, die als Reaktionskomponenteninstanz bezeichnet wird.
Eine React-Komponente kann den Status enthalten und hat Zugriff auf die React Lifecycle-Methoden. Es muss mindestens eine renderMethode haben, die beim Aufrufen ein Reaktionselement (-tree) zurückgibt. Bitte beachten Sie, dass Sie React Component Instances niemals selbst erstellen, sondern von React für Sie erstellen lassen.
typeEigenschaften als native HTML-Elemente haben._Es ist wichtig, diese Unterscheidung hier zu treffen, da das Element nicht das ist, was wir auf dem Bildschirm sehen, sondern die Objektdarstellung das ist, was gerendert wird.
createElementMethode können wir eine Objektdarstellung eines DOM-Knotens (auch bekannt als React-Element) erstellen .
const element = React.createElement(
'div',
{id: 'login-btn'},
'Login'
)
Hier werden createElementdrei Argumente angeführt
Login)createElementAufruf gibt ein Objekt zurück
{
type: 'div',
props: {
children: 'Login',
id: 'login-btn'
}
}
Wenn dies in das DOM gerendert wird (mit ReactDOM.render), haben wir einen neuen DOM-Knoten, der so aussieht:
<div id='login-btn'>Login</div>

Im Allgemeinen wird React von einem Komponenten-First-Ansatz aus gelehrt. Das Verständnis von Elementen-First ermöglicht jedoch einen reibungslosen Übergang zu Komponenten.
Eine Komponente ist eine Funktion oder eine Klasse, die optional Eingaben akzeptiert und ein React-Element zurückgibt.
Eine Reaktionskomponente ist eine Vorlage. Eine Blaupause. Eine globale Definition. Dies kann entweder eine Funktion oder eine Klasse sein (mit einer Renderfunktion).
Wenn reag eine Klasse oder eine Funktion als erstes Argument sieht, prüft es, welches Element es angesichts der entsprechenden Requisiten rendert, und setzt dies fort, bis keine createElementAufrufe mehr vorhanden sind, deren erstes Argument eine Klasse oder eine Funktion ist .
Wenn React ein Element mit einem Funktions- oder Klassentyp sieht, konsultiert es diese Komponente, um zu erfahren, welches Element es angesichts der entsprechenden Requisiten zurückgeben soll.
Am Ende dieses Prozesses verfügt React über eine vollständige Objektdarstellung des DOM-Baums. Dieser gesamte Prozess wird in React als Versöhnung bezeichnet und jedes Mal ausgelöst setStateoder ReactDOM.renderaufgerufen.
Die Klassensyntax ist eine der häufigsten Methoden zum Definieren einer React-Komponente. Es ist zwar ausführlicher als die funktionale Syntax, bietet jedoch mehr Kontrolle in Form von Lifecycle-Hooks.
Erstellen Sie eine Klassenkomponente
// MyComponent.js
import React, { Component } from 'react';
class MyComponent extends Component {
render() {
return (
<div>This is my component.</div>
);
}
}
export default MyComponent;
Verwenden Sie es in jeder anderen Komponente
// MyOtherComponent.js
import React, { Component } from 'react';
import MyComponent from './MyComponent';
class MyOtherComponent extends Component {
render() {
return (
<div>
<div>This is my other component.</div>
<MyComponent />
</div>
);
}
}
export default MyOtherComponent;
Verwenden Sie Requisiten
<MyComponent myProp="This is passed as a prop." />
Auf Requisiten kann mit zugegriffen werden this.props
class MyComponent extends Component {
render() {
const {myProp} = this.props;
return (
<div>{myProp}</div>
);
}
}
Status verwenden
class MyComponent extends Component {
render() {
const {myState} = this.state || {};
const message = `The current state is ${myState}.`;
return (
<div>{message}</div>
);
}
}
Verwenden von Lifecycle-Hooks
class MyComponent extends Component {
// Executes after the component is rendered for the first time
componentDidMount() {
this.setState({myState: 'Florida'});
}
render() {
const {myState} = this.state || {};
const message = `The current state is ${myState}.`;
return (
<div>{message}</div>
);
}
}
Funktionsbasierte Komponenten
Mit createElement
function Button ({ addFriend }) {
return React.createElement(
"button",
{ onClick: addFriend },
"Add Friend"
)
}
function User({ name, addFriend }) {
return React.createElement(
"div",
null,
React.createElement(
"p",
null,
name
),
React.createElement(Button, { addFriend })
)
}
Mit was createElementkehrt zurück
function Button ({ addFriend }) {
return {
type: 'button',
props: {
onClick: addFriend,
children: 'Add Friend'
}
}
}
function User ({ name, addFriend }) {
return {
type: 'div',
props: {
children: [
{
type: 'p',
props: {
children: name
}
},
{
type: Button,
props: {
addFriend
}
}
]
}
}
}
Hier haben wir eine ButtonKomponente, die eine onLoginEingabe akzeptiert und ein React-Element zurückgibt.
ButtonKomponente erhält eine onLoginMethode als Eigenschaft.idAttribut getan haben.React Element- Es ist ein einfaches Objekt, das einen DOM-Knoten und seine Attribute oder Eigenschaften beschreibt, die Sie sagen können. Es ist ein unveränderliches Beschreibungsobjekt, auf das Sie keine Methoden anwenden können.
Z.B -
<button class="blue"></button>
React Component- Es ist eine Funktion oder Klasse, die eine Eingabe akzeptiert und ein React-Element zurückgibt. Es muss Verweise auf seine DOM-Knoten und auf die Instanzen der untergeordneten Komponenten beibehalten.
const SignIn = () => (
<div>
<p>Sign In</p>
<button>Continue</button>
<button color='blue'>Cancel</button>
</div>
);
Eine Komponente ist eine Fabrik zum Erstellen von Elementen.
Ein Element ist ein einfaches Objekt, das beschreibt, was auf dem Bildschirm in Bezug auf die DOM-Knoten oder andere Komponenten angezeigt werden soll. Elemente können andere Elemente in ihren Requisiten enthalten. Das Erstellen eines React-Elements ist billig. Sobald ein Element erstellt wurde, wird es nie mehr mutiert. Die Objektdarstellung des React-Elements wäre wie folgt:
const element = React.createElement(
'div',
{id: 'login-btn'},
'Login'
)
Das obige createElement gibt als Objekt wie folgt zurück:
{
type: 'div',
props: {
children: 'Login',
id: 'login-btn'
}
}
Und schließlich wird es mit ReactDOM.render wie folgt in das DOM gerendert.
<div id='login-btn'>Login</div>
Während eine Komponente auf verschiedene Arten deklariert werden kann. Es kann eine Klasse mit einer render () -Methode sein. Alternativ kann es in einfachen Fällen als Funktion definiert werden. In beiden Fällen werden Requisiten als Eingabe verwendet und ein Elementbaum als Ausgabe zurückgegeben. JSX wurde am Ende als createElement transpiliert.
function Button ({ onLogin }) {
return React.createElement(
'div',
{id: 'login-btn', onClick: onLogin},
'Login'
)
}
Hier ist meine Einstellung:
Elementbeschreibt, wie das VDOM erstellt wird. Es ist im Grunde eine "eingefrorene" Version des entsprechenden Component Instance.
Wenn alles wäre, functional componentwäre keine zusätzliche Reaktion erforderlich Element. Die functional componentHierarchie könnte den VDOM-Baum direkt erzeugen.
Eine Reaktionshierarchie Component Instance( tree) ist eine "Fabrik", und diese Fabrik wird durch die Requisiten parametrisiert, die der Wurzelreaktion zugeführt werden, Component Instanceund durch den gesamten Zustand, der irgendwo im Component InstanceBaum "gespeichert" ist .
Die Reaktion Elementist also im Grunde ein "abstrakter Syntaxbaum", der in das eigentliche VDOM kompiliert wird.
Warum also nicht das VDOM direkt mit der Reaktion generieren Component Instances? Das ist hier die eigentliche Frage.
Auf den ersten Blick verstehe ich nicht, warum das nicht möglich wäre. Die Antwort lautet also höchstwahrscheinlich, dass es sich um eine Frage der Leistung handelt.
Die Reaktion Elementist eine Abstraktionsebene zwischen dem VDOM und dem Component Instance, warum diese Abstraktion benötigt wird, ist mir nicht ganz klar, höchstwahrscheinlich erlaubt sie Optimierungen. Beispielsweise wird der ElementBaum nicht vollständig gerendert, wenn eine Lebenszyklusmethode auf dem Component Instancebesagt, dass dieser Teilbaum nicht gerendert werden muss.
In diesem Fall "benötigt" die Logik, die diese Optimierung handhabt, diese zusätzliche Indirektionsebene - da die Informationen an einem Ort gespeichert werden müssen, an dem ein Teil des VDOM nicht mit dem neuen VDOM verglichen werden sollte, noch mehr, vielleicht der neue VDOM sollte überhaupt nicht berechnet werden. Die Verwendung einer zusätzlichen Indirektionsebene vereinfacht die Renderlogik und führt zu einer saubereren und wartbareren Implementierung - wie ich mir vorstellen kann.
Dieses Konzept in Haskell heißt " Heben ":
Zum Beispiel sind Monaden in Haskell perfekte Beispiele für solche Aufzüge.
Eine Monade ist eine Art Beschreibung einer Berechnung, die wie folgt als Wert gespeichert werden kann 42. In ähnlicher Weise reagieren ElementsElemente einer Beschreibung, wie das "neue" VDOM berechnet wird. Wenn jemand es berechnen will.
Dieser Vortrag beschreibt dieses Konzept einer "zusätzlichen" Indirektion mit einigen einfachen Beispielen :
Mit anderen Worten: Vorzeitige Optimierung ist die Wurzel allen Übels.
Oder: Grundsatz der Softwareentwicklung
Der Grundsatz der Softwareentwicklung (FTSE) ist ein Begriff, der von Andrew Koenig stammt, um eine Bemerkung von Butler Lampson 1 zu beschreiben, die dem verstorbenen David J. Wheeler zugeschrieben wird: 2
Wir können jedes Problem lösen, indem wir eine zusätzliche Indirektionsebene einführen.
Nach meinem Verständnis sind Reagieren Elementsein Implementierungsdetail, um die Komplexität angemessen zu handhaben und eine gewisse Optimierung (Leistung) zu ermöglichen. Ich verstehe nicht, warum man diese zusätzliche Indirektion nicht loswerden konnte - im Prinzip - reagieren würde immer noch "genauso gut" funktionieren - aber es könnte sehr langsam sein, die Implementierung und Wartung der reaktionsfähigen "Engine" selbst wäre wahrscheinlich ein Albtraum .
Bitte korrigieren Sie mich, wenn mir hier etwas fehlt.
Zitieren eines WICHTIGEN Teils der Antwort von user6445533:
type, eine Zeichenfolge, die ein HTML-Tag oder eine Referenz darstellt, die auf eine Reaktionskomponente verweist
DAS IST DER SCHLÜSSEL ^^^^
Element IST NICHT VDOM.
A React Elementist das, was Sie als grundlegendes HTML-Element (genauer gesagt dom) betrachten würden. Es ist nur eine Möglichkeit, Elemente zu erstellen, ohne das umstrittene jsx-Format zu verwenden.
A React Componentist das, was Sie als Objekt betrachten können. Es hat seine Methoden, unterstützt React lifecyclesund ist im Allgemeinen nicht wiederverwendbar (zumindest noch keine Wiederverwendung gefunden, willkommen zu Beispielen). Es muss unbedingt eine Renderfunktion haben.
A React Classnennt man eine Klasse. Funktionalität weise React Classund React Componentsind gleich. Nur die Syntax ist die eigentliche Änderung, auf der React Componentbasiert ES6 syntax. Eine weitere wichtige Änderung ist, dass die Standardbindung von Funktionen an diese nicht mehr unterstützt wird, es sei denn, Sie verwenden Pfeilfunktionen. Mixinswerden ab sofort auch nicht mehr unterstützt ES6.
Elemente sind Thunks.
Mit React können Sie Benutzeroberflächen als reine Funktionen definieren, die im Anwendungsstatus definiert sind. Dies könnte implementiert werden, indem die gesamte Benutzeroberfläche bei jeder Statusänderung berechnet wird. Dies wäre jedoch teuer. Elemente sind rechnerische Beschreibungen (Thunks). Wenn sie sich nicht ändern und Sie PureComponents verwenden, wird React diesen Teilbaum nicht neu berechnen.