Редагувати 2015 рік
Хтось зробив проект щодо NPM зі своїм рішенням: https://github.com/lovasoa/react-contenteditable
Редагувати 06/2016: Щойно я спричинив нову проблему, яка виникає, коли браузер намагається «переформатувати» той HTML, який ви йому щойно надали, що призводить до того, що компонент завжди буде повторно рендерінг. Побачити
Редагувати 07/2016: ось мій виробничий контент Придатне втілення. У ньому є кілька додаткових варіантів, react-contenteditableякі ви хочете, зокрема:
- блокування
- імперативний API, що дозволяє вставляти HTML-фрагменти
- можливість переформатувати зміст
Підсумок:
Рішення FakeRainBrigand деякий час працювало для мене досить добре, поки у мене не виникли нові проблеми. ContentEditables - це біль, і не дуже легко впоратися з React ...
Цей JSFiddle демонструє проблему.
Як бачите, коли ви вводите деякі символи та натискаєте на Clear, вміст не очищається. Це тому, що ми намагаємось відновити змістовне значення до останнього відомого значення віртуального дому.
Тож здається, що:
- Вам потрібно
shouldComponentUpdateзапобігти стрибкам позиції карет
- Якщо ви використовуєте
shouldComponentUpdateцей спосіб, ви не можете покластися на алгоритм VDOM, що відрізняється від React .
Тому вам потрібен додатковий рядок, щоб кожен раз, коли shouldComponentUpdateповертається так, ви впевнені, що вміст DOM фактично оновлюється.
Отже, версія тут додає componentDidUpdateта стає:
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;
}
});
Віртуальний дім залишається застарілим, і це може бути не найефективнішим кодом, але принаймні він працює :) Моя помилка вирішена
Деталі:
1) Якщо ви покладете на параметр shouldComponentUpdate, щоб уникнути стрибків карет, то змістовна відповідь ніколи не повторюється (принаймні на натискання клавіш)
2) Якщо компонент ніколи не видається на ключовому обведенні, тоді React зберігає застарілий віртуальний дом для цього вмісту.
3) Якщо React зберігає застарілу версію contenteditable у своєму віртуальному дереві dom, то якщо ви спробуєте відновити contenteditable до значення, застарілого у віртуальному dom, то під час віртуального dom diff, React обчислить, що ніяких змін у зверніться до DOM!
Це відбувається в основному, коли:
- у вас спочатку порожній контент-придатний (повиненComponentUpdate = true, prop = "", попередній vdom = N / A),
- користувач вводить якийсь текст, і ви запобігаєте візуалізації (shouldComponentUpdate = false, prop = text, попередній vdom = "")
- після того, як користувач натисне кнопку підтвердження, ви бажаєте спорожнити це поле (shouldComponentUpdate = false, prop = "", попередній vdom = "")
- як і щойно створений, і старий vdom є "", React не торкається дому.
initialValueвstateі використовувати його вrender, але я не дозволяю Реагувати поновлення його далі.