Ein kleiner React -Haken, um Elemente in vollständig reendbare und bearbeitbare Inhaltsoberflächen wie Code -Editoren zu verwandeln, die inhaltliche (und Magie) verwendet werden
useEditable ist ein kleiner Haken, der es Elementen ermöglicht, contenteditable zu sein, während sie dennoch vollständig wiedergegeben werden. Dies ist ideal, um kleine Code -Editoren oder Prosa -Textbereiche in nur 2kB zu erstellen!
Ziel ist es, jedes Element bearbeitbar zu sein und gleichzeitig normale Reakte -Elemente zu vermitteln - keine innerHTML und muss mit dem Betrieb oder dem Rendieren von RAW -HTML oder einem vollständigen Editor -Projekt von Grund auf ein volles Editor -Projekt starten.
Schauen Sie sich die vollständige Demo auf Codesandbox mit prism-react-renderer an!
Installieren Sie zunächst neben react : use-editable :
yarn add use-editable
# or
npm install --save use-editable Sie können dann useEditable importieren und einen HTMLElement Ref und einen onChange -Handler übergeben.
import React , { useState , useRef } from 'react' ;
import { useEditable } from 'use-editable' ;
const RainbowCode = ( ) => {
const [ code , setCode ] = useState ( 'function test() {}nconsole.log("hello");' ) ;
const editorRef = useRef ( null ) ;
useEditable ( editorRef , setCode ) ;
return (
< div className = "App" >
< pre
style = { { whiteSpace : 'pre-wrap' , fontFamily : 'monospace' } }
ref = { editorRef }
>
{ code . split ( / r?n / ) . map ( ( content , i , arr ) => (
< React . Fragment key = { i } >
< span style = { { color : `hsl( ${ ( ( i % 20 ) * 17 ) | 0 } , 80%, 50%)` } } >
{ content }
</ span >
{ i < arr . length - 1 ? 'n' : null }
</ React . Fragment >
) ) }
</ pre >
</ div >
) ;
} ; Und genau so haben wir uns an unseren editorRef useEditable , was auf das <pre> -Elements, das gerendert wird, und zum setCode , der unseren Status mit Code enthält, verweist.
Diese Bibliothek wurde dagegen getestet und sollte ordnungsgemäß verwendet werden:
In IE 11 sind Probleme bekannt, da die MutationObserver -Methode nicht in der Lage ist, Textknoten zu lesen, die über das contenteditable entfernt wurden.
Traditionell gab es drei Optionen bei der Auswahl der Bearbeitungsflächen in React. Entweder könnte man ein großes Projekt wie Prosemrror / Codemirror oder ähnliches entscheiden, das die Kontrolle über einen Großteil der Bearbeitungs- und Rendering -Ereignisse übernimmt und daher eher aufmerksam gemacht wird, oder es ist möglich, contenteditable zu verwenden, um nur in den Inhalten des Elements ersetzt zu werden, oder letztendlich eine textarea mit einem überlappenden div -Rendern kombinieren kann.
Alle drei Optionen ermöglichen nicht viel Anpassungen in Bezug auf das, was tatsächlich wiedergegeben wird, oder setzen unangemessene Einschränkungen dafür ein, wie einfach es ist, den Inhalt eines bearbeitbaren Inhalts zu rendern und zu verwalten.
Was macht das Rendern eines contenteditable Elements so schwer?
In der Regel ist dies schwierig, weil sie das DOM direkt bearbeiten. Dies führt dazu, dass die meisten Rendering -Bibliotheken wie React und Preact verwirrt werden, da ihre zugrunde liegenden virtuellen DOMs nicht mehr mit der tatsächlichen DOM -Struktur übereinstimmen. Um dieses Problem zu verhindern, erzeugt use-editable einen MutationObserver , der über alle Änderungen nach dem contenteditable Element übergeht. Bevor es diese Änderungen berichtet, um zu reagieren, rollt sie zuerst alle Änderungen am DOM zurück, so dass React sieht, was sie erwartet.
Darüber hinaus bewahrt es auch die aktuelle Position der Pflege, die Auswahl und stellt sie wieder her, sobald React das DOM selbst aktualisiert hat. Dies ist eine eher häufige Technik für contenteditable Redakteure, aber die MutationObserver Addition ermöglicht die use-editable um einen anderen Ansichtsbibliothek den Inhalt des Elements aktualisieren zu lassen.
Derzeit muss entweder der Textinhalt der gerenderten Elemente schließlich genau mit der Codeeingabe übereinstimmen, oder Ihre Implementierung muss in der Lage sein, den gerenderten Textinhalt wieder in das, was Sie als Status verwenden, umzuwandeln. Dies ist eine Einschränkung, wie contenteditable es funktioniert, da sie nur den tatsächlichen DOM -Inhalt erfassen. Da use-editable nicht eine vollständige Komponente sein kann, die den Render-Zyklus verwaltet, muss er keinen zusätzlichen Zustand behalten, aber nur den Text des DOM an den onChange Rückruf übergeben.
Mit dem onChange Rückruf erhalten Sie außerdem ein Position , das die Cursorposition, die aktuelle Zeilennummer und die Inhalt der Linie bis zum Cursor beschreibt, was für die automatische Verlängerung nützlich ist, die dann mit der update angewendet werden kann, die useEditable , um die Cursorposition zu aktualisieren.
Das erste Argument ist elementRef und akzeptiert ein Ref -Objekt vom Typ RefObject<HTMLElement> das auf das Element hinweist, das bearbeitbar werden sollte. Dieser Schiedsrichter darf während der Laufzeit des Hakens null oder ändern. Solange die Veränderungen des Ref durch React ausgelöst werden, sollte sich alles wie erwartet verhalten.
Das zweite Argument ist onChange und akzeptiert einen Rückruf vom Typ (text: string, pos: Position) => void der aufgerufen wird, wenn der Inhalt der contenteditable Änderungen aufgerufen wird. Dies muss so eingerichtet werden, dass es einen Umbau des Inhalts des Elements auslöst.
Der text , den onChange erhält, ist nur die Textdarstellung des Inhalts des Elements, während die von ihm empfangene Position die aktuelle Position des Cursors, die Zeilennummer (null-indexiert) und den Inhalt der aktuellen Linie bis zum Cursor enthält, der für Autosuggs nützlich ist.
Das dritte Argument ist ein optionales options . Dies akzeptiert derzeit zwei Optionen, um das Bearbeitungsverhalten des Hooks zu ändern:
disabled Option deaktiviert die Bearbeitung auf dem bearbeitbaren, indem das contentEditable Attribut erneut entfernt wird.indentation kann eine Reihe von angezeigten Räumen für die Einklingung sein. Dies ermöglicht auch das verbesserte Tab -Schlüsselverhalten, das die aktuelle Zeile einbringt oder die aktuelle Linie in der Lage versetzt, wenn die Verschiebung abgehalten wird (Beachten Sie, dass der Editor als Fokusfalle fungiert!) Wenn options.indentation eingestellt sind, wird die Einführung der useEditable verhindern und fügt stattdessen die angegebene Menge an Weißspaces ein, die die Handhabung von Spalten erheblich erleichtert.
Zusätzlich gibt der useEditable Hook einen Edit mit verschiedenen Methoden zurück, wie unten dokumentiert.
Edit.update(content: string): void
Ersetzt den gesamten Inhalt des Bearbeitbaren, während die Pflegeposition angepasst wird. Dadurch verschiebt sich die Pflege durch den Differenz der Länge zwischen dem aktuellen Inhalt und dem übergebenen Inhalt.
Edit.insert(append: string, offset?: number): void
Fügt neue Text in der Pflegeposition ein, während Sie den Text in Bereich des Offsetes löschen (was negative Offsets akzeptiert). Wenn beispielsweise offset auf -1 eingestellt ist, wird ein einzelnes Zeichen links hinter der Pflege gelöscht, bevor ein neuer Text eingefügt wird. Wenn es auf 2 gesetzt ist, werden zwei Zeichen rechts von den Karos gelöscht. Der append kann auch auf eine leere Zeichenfolge eingestellt werden, um nur Löschungen anzuwenden, ohne einen Text einzufügen. Wenn ein Text ausgewählt wird, wird er einfach zuerst gelöscht und offset wird ignoriert.
Edit.move(pos: number | { row: number; column: number }): void
Dies bewegt die Pflege in die angegebene Position. Die Position kann entweder ein Zeichenindex (eine number ) oder Koordinaten sein, die eine row und column separat angeben.
Edit.getState(): { text: string; position: Position }
Diese Methode ermöglicht das Erhalten des aktuellen Zustands des bearbeitbaren, der das entspricht, was bei onChange normalerweise erhält. Dies ist nützlich, wenn Sie benutzerdefinierte Bearbeitungsaktionen in einem Key Down -Handler hinzufügen oder wenn sie ansonsten programmgesteuert onChange , während das Bearbeitbare ausgewählt ist.
react-live , an dem ich gearbeitet habe, hatte einen der frühen winzigen, contenteditable Redakteure. (Aber mit rohen HTML -Updates)react-simple-code-editor war die erste (?) Bibliothek, in der eine Split-TextArea und die Rendering-Oberflächenimplementierung verwendet wurden, in der eine schöne Bearbeitungs-API aussehen sollte.codejar enthält die besten Tricks, um die Auswahl zu verwalten, obwohl es einige Firefox -Problemumgehungen fehlen. Es verwendet auch RAW -HTML -Hervorhebung / Aktualisierung.codemirror.next ist eine unschätzbare Quelle, um verschiedene Techniken beim Umgang mit Texteingabe- und DOM -Aktualisierungs -Tricks zu sehen. Stable: Förderbar plant nicht, neue Funktionen für dieses Projekt zu entwickeln. Wir reagieren immer noch auf Fehlerberichte und Sicherheitsbedenken. Wir begrüßen immer noch PRs für dieses Projekt, aber PRs, die neue Funktionen enthalten, sollten klein und einfach zu integrieren und nicht zu brechen. Änderungen enthalten.