Редагувати 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
, але я не дозволяю Реагувати поновлення його далі.