Detaillierte Erklärung zur Verwendung von React.cloneElement

Detaillierte Erklärung zur Verwendung von React.cloneElement

Da wir die Wartung einiger Projekte selbst übernehmen müssen, wurde der Technologie-Stack des Teams kürzlich von Vue auf React umgestellt. Als React-Neuling und weil ich immer gerne neue Dinge durch Quellcode lerne, habe ich mich entschieden, die Verwendung von React durch das Lesen des Quellcodes des berühmten Projekts antd zu erlernen.

Beim Lesen des Quellcodes stellte ich fest, dass viele Komponenten die API React.cloneElement verwendeten. Obwohl ich anhand des Namens erraten konnte, was es tat, kannte ich seine spezifische Funktion nicht. Dann las ich die offizielle Dokumentation, in der die Funktion klar beschrieben wurde, uns jedoch nicht gesagt wurde, in welchen Szenarien wir es verwenden müssen. Daher habe ich einige Verwendungsszenarien basierend auf der Beschreibung im Dokument zusammengefasst, mit der Verwendung des Quellcodes kombiniert und mich an Google und Stackoverflow orientiert.

Die Rolle von cloneElement

React.cloneElement(
 Element,
 [Requisiten],
 [...Kinder]
)

Schauen Sie sich zunächst die offizielle Dokumentation dieser API an:

Klonen und geben Sie ein neues React-Element zurück, wobei Sie das Element als Ausgangspunkt verwenden. Das resultierende Element enthält die Eigenschaften des ursprünglichen Elements, wobei die neuen Eigenschaften oberflächlich integriert sind. Neue untergeordnete Elemente ersetzen vorhandene untergeordnete Elemente. Schlüssel und Referenz des ursprünglichen Elements bleiben erhalten.

Um zusammenzufassen:

  1. Klonen Sie das Originalelement und geben Sie ein neues React-Element zurück.
  2. Behalten Sie die Requisiten des Originalelements bei, fügen Sie neue Requisiten hinzu und führen Sie die beiden oberflächlich zusammen.
  3. Schlüssel und Referenz bleiben erhalten, da es sich auch um Eigenschaften handelt und sie daher auch geändert werden können.
  4. Laut dem Quellcode von React können wir ab dem dritten Parameter beliebig viele Kindelemente definieren. Wenn neue Kinder definiert werden, werden die ursprünglichen Kinder ersetzt.

Anwendungsszenarien

Gemäß der obigen Definition können wir diese API nach Bedarf in verschiedenen Szenarien verwenden.

Neue Requisiten hinzufügen

Wenn wir eine gemeinsame Komponente erstellen, möchten wir jedem untergeordneten Element gemäß der internen Logik unterschiedliche Klassennamen hinzufügen. Zu diesem Zeitpunkt können wir den className ändern:

Angenommen, wir haben eine Timeline-Komponente, mit der wir bei Bedarf mehrere TimelineItem definieren können. Intern möchten wir dem letzten TimelineItem eine Klasse timeline-item-last hinzufügen, um einen Spezialeffekt zu rendern. Zu diesem Zeitpunkt können wir Folgendes tun:

const MyTimeline = () => {
 zurückkehren (
  <Zeitleiste>
   <TimelineItem>01.06.2020</TimelineItem>
   <TimelineItem>08.06.2020</TimelineItem>
   <TimelineItem>05.07.2020</TimelineItem>
  </Zeitleiste>
 )
}

// Innerhalb der Zeitleiste könnte die Logik wie folgt aussehen: „import class from 'classnames';“
const Timeline = Requisiten => {
 // ...
 // ...
 const itemCount = React.children.count(props.children);
 const items = React.children.map(props.children, (item, index) => {
  returniere React.cloneElement(item, {
   Klassenname: Klasse ([
    Artikel.Eigenschaften.Klassenname,
    "Zeitleistenelement",
    Index === Anzahl – 1? 'letztes Timeline-Element': ''
   ])
  })
 }
 return <div className={'timeline'}>{ Elemente }</div>
}

Zusätzlich zum Hinzufügen von className können Sie Unterkomponenten auch dynamisch weitere Props-Informationen hinzufügen. Switch von react-router fügt passenden Unterkomponenten location und computedMatch Informationen hinzu:

Klasse Switch erweitert React.Component {
 rendern() {
  zurückkehren (
   <RouterContext.Verbraucher>
    {Kontext => {
     invariant(context, "Sie sollten <Switch> nicht außerhalb eines <Routers> verwenden");

     const Standort = this.props.location || Kontext.Standort;

     Lass das Element übereinstimmen;

     // Wir verwenden React.Children.forEach anstelle von React.Children.toArray().find()
     // hier, weil toArray Schlüssel zu allen untergeordneten Elementen hinzufügt und wir nicht wollen
     // um ein Unmounten/Remounten für zwei <Route>s auszulösen, die dasselbe rendern
     // Komponente unter verschiedenen URLs.
     React.Children.fürEach(this.props.children, Kind => {
      wenn (match == null und React.isValidElement(child)) {
       Element = Kind;

       const Pfad = Kind.props.Pfad || Kind.props.von;

       Übereinstimmung = Pfad
        ? matchPath(Standort.Pfadname, { ...child.props, Pfad })
        : Kontext.Übereinstimmung;
      }
     });

     Revanche
      React.cloneElement(Element, {Standort, berechnete Übereinstimmung: Übereinstimmung})
      : null;
    }}
   </RouterContext.Consumer>
  );
 }
}

Ereignisse, die Requisiten verändern

Angenommen, wir haben eine Tab-Komponente, die mehrere TabPane Unterkomponenten enthält. Wir möchten das onClick -Ereignis der Registerkarte auslösen, wenn auf jede TabPane Unterkomponente geklickt wird. Der Benutzer kann für jedes TabPane ein unabhängiges onClick -Ereignis definieren. In diesem Fall müssen wir das onClick -Ereignis der Unterkomponente ändern:

const Tab = props => {
 const { beim Klicken } = Requisiten;
 const tabPanes = React.children.map(props.children, (tabPane, index) => {
  const paneClick = () => {
   beiKlick und beiKlick(Index);
   tabPane.props?.onClick();
  }
  returniere React.cloneElement(tabPane, {
    bei Klick: Fensterklick,
  })
 })
 return <div>{ Tabulatortasten }</div>
}

Benutzerdefinierter Stil

Beim Erstellen einer Komponente namens FollowMouse können Benutzer die Inhaltskomponente Content definieren. Wenn sich die Maus bewegt, wird die Position von Content automatisch entsprechend der Größe des Inhalts berechnet, um ein Überlaufen des Bildschirms zu vermeiden. Zu diesem Zeitpunkt können wir cloneElement verwenden, um seinen Stil dynamisch zu ändern.

// Der Einfachheit halber werden Mausereignisse hier weggelassen.
const FollowMouse = props => {
 const { Inhalt } = Requisiten;
 const customContent = React.isValidElement ? Inhalt : <span>{ Inhalt }</span>
 const getOffset = () => {
  zurückkehren {
   Position: 'absolut',
   Spitze: ...,
   links: ...,
  }
 }
 const renderContent = React.cloneElement(custonContent, {
  Stil: {
   …getOffset()
  }
 })
 return <div>{ renderContent() }</div>
}

Schlüssel hinzufügen

Wenn wir eine Liste von Elementen erstellen, können wir jedem Knoten über cloneElement einen Schlüssel hinzufügen.

const ComponentButton = Eigenschaften => {
 const { addonAfter, untergeordnete Elemente } = Requisiten;
 const button = <button key='button'>{ untergeordnete Elemente }</button>
 const-Liste = [Schaltfläche, Add-onAfter? React.cloneElement(AddonAfter, {Schlüssel: 'Button-Addon'}: null)
 zurück <div>{ Liste } <div>
}

Zusammenfassen

Bei der Entwicklung komplexer Komponenten fügen wir den untergeordneten Komponenten häufig je nach Bedarf verschiedene Funktionen oder Anzeigeeffekte hinzu. Das react Element selbst ist ein unveränderliches Objekt. props.children sind eigentlich nicht children selbst, sondern nur der Deskriptor der children . Wir können keine seiner Eigenschaften ändern, sondern nur seinen Inhalt lesen. Daher können wir React.cloneElement seine Elemente kopieren und neue Props ändern oder hinzufügen, um unsere Ziele zu erreichen.

Dank des leistungsstarken Kombinationsmodus von React ist dies natürlich nicht auf props.children beschränkt. Unabhängig davon, ob props.left oder props.right oder andere übergebene props vorhanden sind, können wir dieses React.cloneElement verwenden, um damit zu arbeiten, solange es sich um ein gültiges React-Element handelt.

Oben finden Sie den detaillierten Inhalt der ausführlichen Erläuterung zur Verwendung von React.cloneElement. Weitere Informationen zur Verwendung von React.cloneElement finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Detaillierte Verwendung von React.Children
  • Anwendungsbeispiele für React Hooks
  • Tiefgreifendes Verständnis der Kernprinzipien von React Native (Bridge of React Native)
  • React+Koa-Beispiel zur Implementierung des Datei-Uploads
  • Beispielcode für die Entwicklung einer H5-Formularseite basierend auf React-Hooks und der Konfiguration der Zarm-Komponentenbibliothek
  • Das Umschalten zwischen React-Antd-Tabs führt zu wiederholter Aktualisierung von Unterkomponenten
  • ReactJs-Grundlagen-Tutorial - Essential Edition
  • ReactRouter-Implementierung

<<:  MySQL 5.5.56-Version (Installation von Binärpaketen) benutzerdefinierter Installationspfad-Schrittdatensatz

>>:  Detaillierte Erklärung der binären und varbinären Datentypen in MySQL

Artikel empfehlen

Tiefgreifendes Verständnis der Rolle von Vuex

Inhaltsverzeichnis Überblick So teilen Sie Daten ...

Teilen Sie 8 MySQL-Fallstricke, die Sie erwähnen müssen

MySQL ist einfach zu installieren, schnell und ve...

MySQL-Datenbank löscht doppelte Daten und behält nur eine Methodeninstanz bei

1. Problemeinführung Nehmen Sie ein Szenario an, ...

So erkennen Sie die Ubuntu-Version mithilfe der Befehlszeile

Methode 1: Verwenden Sie das Dienstprogramm lsb_r...

Docker startet im Status „Beendet“

Nach dem Docker-Lauf ist der Status immer „Beende...

MySQL 5.7.17 Winx64 Installations- und Konfigurations-Tutorial

Heute habe ich die MySQL-Datenbank erneut auf mei...

Lösen Sie das Problem der verstümmelten Zeichen im Tomcat10 Catalina-Protokoll

Laufumgebung, Idea2020-Version, Tomcat10, beim Au...

Details zu Linux-Dateideskriptoren, Dateizeigern und Inodes

Inhaltsverzeichnis Linux - Dateideskriptor, Datei...