Dieser Artikel vermittelt Ihnen hauptsächlich ein tiefgreifendes Verständnis der hochrangigen React-Komponenten. Ich hoffe, dass Sie ein klareres Verständnis der hochrangigen React-Komponenten haben.
1. In React ist die Komponente höherer Ordnung (HOC) eine fortschrittliche Technologie zur Wiederverwendung von Komponentenlogik. HOC ist nicht Teil der React API. Ein HOC ist eine Funktion, die eine Komponente übernimmt und eine neue Komponente zurückgibt. In React sind Komponenten die Grundeinheit der Code-Wiederverwendung.
2. Um HOCs zu erklären, nehmen Sie die folgenden zwei Beispiele
Die CommentList-Komponente rendert eine Kommentarliste und die Daten in der Liste stammen aus externen Quellen.
class CommentList extends React.Component { constructor() { super(); this.handleChange = this.handleChange.bind(this); this.state = { // "DataSource" is some global data source comments: DataSource.getComments() }; } componentDidMount() { // Subscribe to changes DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { // Clean up listener DataSource.removeChangeListener(this.handleChange); } handleChange() { // Update component state whenever the data source changes this.setState({ comments: DataSource.getComments() }); } render() { return ( <p> {this.state.comments.map((comment) => ( <Comment comment={comment} key={comment.id} /> ))} </p> ); } }
Als nächstes kommt die BlogPost-Komponente, die zum Anzeigen eines Blog-Beitrags verwendet wird.
class BlogPost extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = { blogPost: DataSource.getBlogPost(props.id) }; } componentDidMount() { DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { DataSource.removeChangeListener(this.handleChange); } handleChange() { this.setState({ blogPost: DataSource.getBlogPost(this.props.id) }); } render() { return <TextBlock text={this.state.blogPost} />; } }
Sie rufen unterschiedliche Methoden von DataSource auf Auch unterschiedlich, aber die meisten ihrer Implementierungen sind gleich:
1 Nach Abschluss des Ladevorgangs wird der DataSource ein Änderungs-Listener hinzugefügt.
Wenn sich die Datenquelle ändert, rufen Sie setState auf.
innerhalb des Listeners 3. Entfernen Sie nach der Deinstallation den Change Listener
Es ist denkbar, dass in großen Anwendungen immer wieder das gleiche Muster des Zugriffs auf DataSource und des Aufrufs von setState auftritt. Wir möchten diesen Prozess abstrahieren, sodass wir diese Logik nur an einer Stelle definieren und sie dann über mehrere Komponenten hinweg teilen.
Als nächstes schreiben wir eine Funktion, die eine Komponente erstellt. Diese Funktion akzeptiert zwei Parameter, von denen einer die Komponente und der andere die Funktion ist. Die withSubscription-Funktion wird unten aufgerufen
const CommentListWithSubscription = withSubscription( CommentList, (DataSource) => DataSource.getComments() ); const BlogPostWithSubscription = withSubscription( BlogPost, (DataSource, props) => DataSource.getBlogPost(props.id) );
Der erste Parameter, der beim Aufruf von withSubscription übergeben wird, ist die verpackte Komponente, und der zweite Parameter ist eine Funktion, die zum Abrufen von Daten verwendet wird.
Wenn CommentListWithSubscription und BlogPostWithSubscription gerendert werden, akzeptieren CommentList und BlogPost eine Requisite namens data, die die aktuell aus der DataSource abgerufenen Daten speichert. Der withSubscription-Code lautet wie folgt:
// This function takes a component... function withSubscription(WrappedComponent, selectData) { // ...and returns another component... return class extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = { data: selectData(DataSource, props) }; } componentDidMount() { // ... that takes care of the subscription... DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { DataSource.removeChangeListener(this.handleChange); } handleChange() { this.setState({ data: selectData(DataSource, this.props) }); } render() { // ... and renders the wrapped component with the fresh data! // Notice that we pass through any additional props return <WrappedComponent data={this.state.data} {...this.props} />; } }; }
HOC ändert weder die Eingabekomponente noch verwendet es Vererbung, um ihr Verhalten wiederzuverwenden. HOC ist nur eine Funktion. Die umschlossene Komponente akzeptiert alle Requisiten des Containers sowie eine neue Requisite (Daten), die zum Rendern der Ausgabe der umschlossenen Komponente verwendet wird. HOC ist es egal, wie die Daten verwendet werden oder warum die Daten verwendet werden, und der verpackten Komponente ist es egal, wo die Daten abgerufen werden.
Da withSubscription nur eine reguläre Funktion ist, können Sie beliebig viele Parameter hinzufügen. Sie können beispielsweise den Namen der Datenstütze konfigurierbar machen, um das HOC weiter von der umhüllten Komponente zu isolieren.
Akzeptieren Sie entweder ein Konfigurations-ShouldComponentUpdate oder konfigurieren Sie die Parameter der Datenquelle
Bei der Verwendung höherwertiger Komponenten müssen einige Dinge beachtet werden.
1. Verändern Sie nicht die Originalkomponente, das ist sehr wichtig
Es gibt folgende Beispiele:
function logProps(InputComponent) { InputComponent.prototype.componentWillReceiveProps = function(nextProps) { console.log('Current props: ', this.props); console.log('Next props: ', nextProps); }; // The fact that we're returning the original input is a hint that it has // been mutated. return InputComponent; } // EnhancedComponent will log whenever props are received const EnhancedComponent = logProps(InputComponent);
Hier gibt es einige Probleme, 1. Die Eingabe Komponente kann nicht mit der erweiterten Komponente verglichen werden. Komponenten werden einzeln wiederverwendet. 2. Wenn Sie andere HOCs auf EnhancedComponent anwenden, wird auch „componentWillReceiveProps“ geändert.
Dieses HOC ist nicht auf Funktionstypkomponenten anwendbar, da Funktionstypkomponenten keinen Lebenszyklus haben. Funktions-HOC sollte Zusammensetzung statt Modifikation verwenden – indem die Eingabekomponente in eine Containerkomponente eingeschlossen wird.
function logProps(WrappedComponent) { return class extends React.Component { componentWillReceiveProps(nextProps) { console.log('Current props: ', this.props); console.log('Next props: ', nextProps); } render() { // Wraps the input component in a container, without mutating it. Good! return <WrappedComponent {...this.props} />; } } }
Diese neuen logProps haben die gleiche Funktionalität wie die alten logProps, während die neuen logProps potenzielle Konflikte vermeiden. Gleiches gilt für Klassentypkomponenten und Funktionstypkomponenten.
2. Verwenden Sie keine HOCs in der Rendermethode
Der Diff-Algorithmus von React verwendet die Identität der Komponente, um zu entscheiden, ob der vorhandene Teilbaum aktualisiert oder der alte Teilbaum abgebaut und ein geladen werden soll Neu: Wenn die von der Render-Methode zurückgegebene Komponente mit der zuvor gerenderten Komponente übereinstimmt (===), aktualisiert React die zuvor gerenderte Komponente über den Diff-Algorithmus. Andernfalls wird der zuvor gerenderte Teilbaum vollständig entladen.
render() { // A new version of EnhancedComponent is created on every render // EnhancedComponent1 !== EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); // That causes the entire subtree to unmount/remount each time! return <EnhancedComponent />; }
Verwenden Sie HOCs außerhalb der Komponentendefinition, sodass die resultierende Komponente nur einmal erstellt wird. In einigen Fällen müssen Sie HOCs dynamisch anwenden, Sie sollten dies in der Lebenszyklusfunktion oder im Konstruktor tun
3. Statische Methoden müssen manuell kopiert werden
Manchmal ist es in React sehr nützlich um statische Methoden für Komponenten zu definieren. Wenn Sie HOCs auf eine Komponente anwenden, verfügt die zurückgegebene neue Komponente über keine statischen Methoden der Originalkomponente, obwohl die ursprüngliche Komponente in eine Containerkomponente eingeschlossen ist.
// Define a static method WrappedComponent.staticMethod = function() {/*...*/} // Now apply an HOC const EnhancedComponent = enhance(WrappedComponent); // The enhanced component has no static method typeof EnhancedComponent.staticMethod === 'undefined' // true
Damit die zurückgegebene Komponente über die statischen Methoden der Originalkomponente verfügt, müssen die statischen Methoden der Originalkomponente in die neue Komponente innerhalb der Funktion kopiert werden.
function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} // Must know exactly which method(s) to copy :( // 你也能够借助第三方工具 Enhance.staticMethod = WrappedComponent.staticMethod; return Enhance; }
4. Die Referenz auf der Containerkomponente wird nicht an die verpackte Komponente übergeben
Obwohl die Requisiten auf der Containerkomponente problemlos sein können an die umhüllte Komponentenkomponente übergeben, aber der Verweis auf die Containerkomponente wird nicht an die umhüllte Komponente übergeben. Wenn Sie eine Referenz für eine über HOCs zurückgegebene Komponente festlegen, bezieht sich diese Referenz auf die äußerste Containerkomponente und nicht auf die umschlossene Komponente.
Verwandte Empfehlungen
React-Beispiel für den Eintrag von höherwertigen Komponenten
So verwenden Sie hochrangige Vue-Komponenten
Das obige ist der detaillierte Inhalt vonReagieren Sie auf die Beispielanalyse einer Komponente höherer Ordnung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!