Modifica 2015
Qualcuno ha realizzato un progetto su NPM con la mia soluzione: https://github.com/lovasoa/react-contenteditable
Modifica 06/2016: ho appena riscontrato un nuovo problema che si verifica quando il browser cerca di "riformattare" l'html che gli hai appena fornito, portando al componente sempre il rendering. Vedere
Modifica 07/2016: ecco il mio contenuto di produzione Implementazione modificabile. Ha alcune opzioni aggiuntive rispetto a react-contenteditable
quelle che potresti desiderare, tra cui:
- bloccaggio
- API imperativa che consente di incorporare frammenti html
- capacità di riformattare il contenuto
Sommario:
La soluzione di FakeRainBrigand ha funzionato abbastanza bene per me per un po 'di tempo fino a quando non ho avuto nuovi problemi. ContentEditables sono una seccatura e non sono davvero facili da gestire con React ...
Questo JSFiddle dimostra il problema.
Come puoi vedere, quando digiti alcuni caratteri e fai clic su Clear
, il contenuto non viene cancellato. Questo perché proviamo a ripristinare il contenteditable all'ultimo valore di dom virtuale noto.
Quindi sembra che:
- Hai bisogno
shouldComponentUpdate
evitare salti di posizione del cursore
- Non puoi fare affidamento sull'algoritmo di diffing VDOM di React se usi
shouldComponentUpdate
questo modo.
Quindi hai bisogno di una riga in più in modo che ogni volta shouldComponentUpdate
restituisce sì, sei sicuro che il contenuto del DOM sia effettivamente aggiornato.
Quindi la versione qui aggiunge un componentDidUpdate
e diventa:
var ContentEditable = React.createClass({
render: function(){
return <div id="contenteditable"
onInput={this.emitChange}
onBlur={this.emitChange}
contentEditable
dangerouslySetInnerHTML={{__html: this.props.html}}></div>;
},
shouldComponentUpdate: function(nextProps){
return nextProps.html !== this.getDOMNode().innerHTML;
},
componentDidUpdate: function() {
if ( this.props.html !== this.getDOMNode().innerHTML ) {
this.getDOMNode().innerHTML = this.props.html;
}
},
emitChange: function(){
var html = this.getDOMNode().innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
this.props.onChange({
target: {
value: html
}
});
}
this.lastHtml = html;
}
});
Il dominio virtuale rimane obsoleto e potrebbe non essere il codice più efficiente, ma almeno funziona :) Il mio bug è stato risolto
Dettagli:
1) Se si inserisce shouldComponentUpdate per evitare salti di accento circonflesso, l'elemento contenteditable non viene mai ripetuto (almeno quando si preme il tasto)
2) Se il componente non viene mai riprodotto nuovamente alla pressione del tasto, React mantiene un dominio virtuale obsoleto per questo contenuto modificabile.
3) Se React mantiene una versione obsoleta di contenteditable nel suo albero dom virtuale, se provi a reimpostare contenteditable al valore obsoleto nel dominio virtuale, durante il differenziale dom virtuale, React calcolerà che non ci sono modifiche a applicare al DOM!
Ciò accade principalmente quando:
- hai inizialmente un contenteditable vuoto (shouldComponentUpdate = true, prop = "", previous vdom = N / A),
- l'utente digita del testo e si impedisce il rendering (shouldComponentUpdate = false, prop = text, previous vdom = "")
- dopo che l'utente fa clic su un pulsante di convalida, si desidera svuotare il campo (shouldComponentUpdate = false, prop = "", previous vdom = "")
- poiché sia il nuovo vdom che il vecchio sono "", React non tocca il dom.
initialValue
instate
e usarlo inrender
, ma non lascio Reagire aggiornamento ulteriormente.