Wie höre ich, um ein Ereignis für eine contentEditable
basierte Steuerung zu ändern ?
var Number = React.createClass({
render: function() {
return <div>
<span contentEditable={true} onChange={this.onChange}>
{this.state.value}
</span>
=
{this.state.value}
</div>;
},
onChange: function(v) {
// Doesn't fire :(
console.log('changed', v);
},
getInitialState: function() {
return {value: '123'}
}
});
React.renderComponent(<Number />, document.body);
initialValue
instate
und verwenden Sie es inrender
, aber ich lasse nicht aktualisiert es weiter reagieren.contentEditable
indem ich meinen Ansatz geändert habe - anstelle einesspan
oderparagraph
habe ich eininput
zusammen mit seinemreadonly
Attribut verwendet.Antworten:
Bearbeiten: Siehe Sebastien Lorbers Antwort, die einen Fehler in meiner Implementierung behebt.
Verwenden Sie das Ereignis onInput und optional onBlur als Fallback. Möglicherweise möchten Sie den vorherigen Inhalt speichern, um das Senden zusätzlicher Ereignisse zu verhindern.
Ich persönlich hätte dies als meine Renderfunktion.
jsbin
Welches verwendet diesen einfachen Wrapper um contentEditable.
quelle
this.setState({html: "something not in the editable div"}})
this.getDOMNode().innerHTML
inshouldComponentUpdate
ist nicht sehr optimiert richtigstate.html
den letzten "bekannten" Wert festlegen möchten. React aktualisiert das DOM nicht, da das neue HTML in Bezug auf React genau das gleiche ist (obwohl das tatsächliche DOM unterschiedlich ist). Siehe jsfiddle . Ich habe keine gute Lösung dafür gefunden, daher sind alle Ideen willkommen.shouldComponentUpdate
sollte rein sein (keine Nebenwirkungen haben).Bearbeiten Sie 2015
Jemand hat mit meiner Lösung ein NPM-Projekt erstellt: https://github.com/lovasoa/react-contenteditable
Bearbeiten 06/2016: Ich habe gerade ein neues Problem festgestellt, das auftritt, wenn der Browser versucht, das HTML, das Sie ihm gerade gegeben haben, neu zu formatieren, was dazu führt, dass die Komponente immer wieder neu gerendert wird. Sehen
Edit 07/2016: Hier ist mein Produktionsinhalt. Bearbeitbare Implementierung. Es gibt einige zusätzliche Optionen
react-contenteditable
, die Sie möglicherweise möchten, darunter:Zusammenfassung:
Die Lösung von FakeRainBrigand hat für mich einige Zeit ganz gut funktioniert, bis ich neue Probleme bekam. ContentEditables sind ein Schmerz und nicht wirklich einfach zu handhaben ...
Diese JSFiddle demonstriert das Problem.
Wie Sie sehen können
Clear
, wird der Inhalt nicht gelöscht , wenn Sie einige Zeichen eingeben und auf klicken . Dies liegt daran, dass wir versuchen, den inhaltsbearbeitbaren Wert auf den letzten bekannten virtuellen Dom-Wert zurückzusetzen.So scheint es, dass:
shouldComponentUpdate
Caret-Positionssprünge verhindernshouldComponentUpdate
diese Methode verwenden.Sie benötigen also eine zusätzliche Zeile, damit Sie bei jeder
shouldComponentUpdate
Rückgabe von yes sicher sind, dass der DOM-Inhalt tatsächlich aktualisiert wird.Die Version hier fügt also ein hinzu
componentDidUpdate
und wird:Der virtuelle Dom bleibt veraltet und es ist möglicherweise nicht der effizienteste Code, aber zumindest funktioniert er :) Mein Fehler ist behoben
Einzelheiten:
1) Wenn Sie shouldComponentUpdate setzen, um Caret-Sprünge zu vermeiden, wird die inhaltsbearbeitbare Datei nie erneut gerendert (zumindest bei Tastenanschlägen).
2) Wenn die Komponente bei einem Tastendruck nie erneut gerendert wird, behält React einen veralteten virtuellen Dom für diese inhaltsbearbeitbare Datei bei.
3) Wenn React eine veraltete Version von contenteditable in seinem virtuellen Dom-Baum beibehält, und wenn Sie versuchen, die contenteditable auf den Wert zurückzusetzen, der im virtuellen Dom veraltet ist, berechnet React während des virtuellen Dom-Diff, dass keine Änderungen an vorgenommen wurden bewerben Sie sich beim DOM!
Dies geschieht meistens, wenn:
quelle
{...this.props}
damit der Client dieses Verhalten von außen anpassen kannshouldComponentUpdate
Code Caret-Sprünge verhindert?Dies ist die einfachste Lösung, die für mich funktioniert hat.
quelle
onInput
wie im Beispiel angegeben zu verwenden.Dies ist wahrscheinlich nicht genau die Antwort, nach der Sie suchen, aber nachdem ich selbst damit zu kämpfen hatte und Probleme mit vorgeschlagenen Antworten hatte, beschloss ich, sie stattdessen unkontrolliert zu machen.
Wenn
editable
prop istfalse
, verwende ichtext
prop so wie es ist, aber wenn es isttrue
, wechsle ich in den Bearbeitungsmodus, in demtext
es keine Auswirkungen hat (aber zumindest flippt der Browser nicht aus). Während dieser ZeitonChange
werden von der Steuerung ausgelöst. Wenn icheditable
wieder zu wechslefalse
, füllt es HTML mit allem, was übergeben wurdetext
:quelle
shouldComponentUpdate
so einfach implementieren, sodass ich selbst nicht mehr vor Caret-Sprüngen gerettet werde. Schließlich habe ich CSS-Pseudoelement-:empty:before
Platzhalter, aber dieseshouldComponentUpdate
Implementierung hat FF und Safari daran gehindert, das Feld zu bereinigen, wenn es vom Benutzer gelöscht wird. Ich habe 5 Stunden gebraucht, um festzustellen, dass ich all diese Probleme mit unkontrolliertem CE umgehen kann.editable
inUncontrolledContentEditable
. Könnten Sie ein lauffähiges Beispiel liefern?editable
von außen. Stellen Sie sich ein Feld vor, das inline bearbeitet werden kann, wenn der Benutzer auf "Bearbeiten" drückt, und das nur dann schreibgeschützt sein sollte, wenn der Benutzer auf "Speichern" oder "Abbrechen" drückt. Wenn es schreibgeschützt ist, verwende ich Requisiten, aber ich höre auf, sie zu betrachten, wenn ich in den „Bearbeitungsmodus“ gehe, und schaue Requisiten erst wieder an, wenn ich sie verlasse.escapeTextForBrowser
zuescapeTextContentForBrowser
.Da nach Abschluss der Bearbeitung der Fokus des Elements immer verloren geht, können Sie einfach den onBlur-Hook verwenden.
quelle
Ich schlage vor, dazu einen mutationsObserver zu verwenden. Es gibt Ihnen viel mehr Kontrolle darüber, was los ist. Außerdem erfahren Sie mehr darüber, wie das Durchsuchen alle Tastenanschläge interpretiert
Hier in TypeScript
quelle
Hier ist eine Komponente, die vieles davon von lovasoa enthält: https://github.com/lovasoa/react-contenteditable/blob/master/index.js
Er shims das Ereignis in der emitChange
Ich verwende einen ähnlichen Ansatz erfolgreich
quelle