Edytuj 2015
Ktoś wykonał projekt na NPM z moim rozwiązaniem: https://github.com/lovasoa/react-contenteditable
Edycja 06/2016: Właśnie napotkałem nowy problem, który pojawia się, gdy przeglądarka próbuje „przeformatować” kod HTML, który właśnie mu przekazałeś, co prowadzi do tego, że komponent zawsze renderuje się ponownie. Widzieć
Edycja 07/2016: oto moja zawartość produkcyjna Edytowalna implementacja. Ma kilka dodatkowych opcji, react-contenteditable
które możesz chcieć, w tym:
- zamykający
- imperatywne API pozwalające na osadzanie fragmentów html
- możliwość ponownego formatowania treści
Podsumowanie:
Rozwiązanie FakeRainBrigand działało dla mnie całkiem dobrze przez jakiś czas, dopóki nie pojawiły się nowe problemy. ContentEditables są uciążliwe i nie są łatwe w obsłudze React ...
Ten JSFiddle demonstruje problem.
Jak widać, po wpisaniu niektórych znaków i kliknięciu Clear
zawartość nie jest czyszczona. Dzieje się tak, ponieważ próbujemy zresetować zawartość edytowalną do ostatniej znanej wartości wirtualnej domeny.
Więc wydaje się, że:
- Musisz
shouldComponentUpdate
zapobiegać skokom pozycji karetki
- Nie możesz polegać na algorytmie porównywania VDOM firmy React, jeśli używasz w
shouldComponentUpdate
ten sposób.
Potrzebujesz więc dodatkowej linii, aby zawsze, gdy shouldComponentUpdate
zwróci wartość tak, masz pewność, że zawartość DOM jest rzeczywiście zaktualizowana.
Tak więc wersja tutaj dodaje a componentDidUpdate
i staje się:
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;
}
});
Wirtualny dom pozostaje nieaktualny i może nie jest to najbardziej wydajny kod, ale przynajmniej działa :) Mój błąd został rozwiązany
Detale:
1) Jeśli umieścisz shouldComponentUpdate, aby uniknąć skoków karetki, treść edytowalna nigdy nie będzie ponownie renderowana (przynajmniej po naciśnięciu klawisza)
2) Jeśli komponent nigdy nie jest ponownie renderowany po naciśnięciu klawisza, React przechowuje nieaktualną wirtualną domenę dla tej zawartości, którą można edytować.
3) Jeśli React zachowuje przestarzałą wersję edytowalnej treści w swoim wirtualnym drzewie dom, to jeśli spróbujesz zresetować zawartość edytowalną do wartości nieaktualnej w wirtualnym dom, to podczas wirtualnego różnic dom, React obliczy, że nie ma żadnych zmian zastosuj do DOM!
Dzieje się tak głównie wtedy, gdy:
- masz początkowo pustą treść do edycji (shouldComponentUpdate = true, prop = "", previous vdom = N / A),
- użytkownik wpisuje tekst, a ty zapobiegasz renderowaniu (shouldComponentUpdate = false, prop = text, previous vdom = "")
- gdy użytkownik kliknie przycisk walidacji, chcesz opróżnić to pole (shouldComponentUpdate = false, prop = "", previous vdom = "")
- ponieważ zarówno nowo utworzone, jak i stare pliki vdom są "", React nie dotyka domeny.
initialValue
gostate
i używamrender
, ale nie pozwalam, aby React go dalej aktualizował.