Как мне прослушать событие изменения для contentEditable
управления на основе?
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
вstate
и использовать его вrender
, но я не позволяю Реагировать обновления его дальше.contentEditable
проблем, изменив свой подход - вместоspan
илиparagraph
я использовалinput
вместе с егоreadonly
атрибутом.Ответы:
Изменить: см . Ответ Себастьяна Лорбера, который исправляет ошибку в моей реализации.
Используйте событие onInput и, возможно, onBlur в качестве запасного варианта. Возможно, вы захотите сохранить предыдущее содержимое, чтобы предотвратить отправку дополнительных событий.
Я бы лично использовал это как функцию рендеринга.
jsbin
Который использует эту простую оболочку для contentEditable.
источник
this.setState({html: "something not in the editable div"}})
this.getDOMNode().innerHTML
вshouldComponentUpdate
не очень оптимизирован правоstate.html
последнее «известное» значение, React не будет обновлять DOM, потому что новый html точно такой же, как и React (даже если фактическая DOM отличается). См. Jsfiddle . Я не нашел для этого хорошего решения, поэтому любые идеи приветствуются.shouldComponentUpdate
должен быть чистым (не иметь побочных эффектов).Изменить 2015
Кто-то сделал проект на NPM с моим решением: https://github.com/lovasoa/react-contenteditable
Редактировать 06/2016: Я только что столкнулся с новой проблемой, которая возникает, когда браузер пытается «переформатировать» HTML-код, который вы ему только что дали, что приводит к постоянному повторному рендерингу компонента. Видеть
Изменить 07/2016: вот моя реализация ContentEditable. У него есть несколько дополнительных опций
react-contenteditable
, которые могут вам понадобиться, в том числе:Резюме:
Решение FakeRainBrigand некоторое время работало у меня нормально, пока у меня не возникли новые проблемы. ContentEditables - это боль, и с ними не так просто справиться с React ...
Этот JSFiddle демонстрирует проблему.
Как видите, когда вы вводите какие-то символы и щелкаете по
Clear
, содержимое не очищается. Это потому, что мы пытаемся сбросить contenteditable до последнего известного значения виртуального dom.Так кажется, что:
shouldComponentUpdate
предотвратить скачки позиции курсораshouldComponentUpdate
этот способ.Таким образом, вам нужна дополнительная строка, чтобы всякий раз, когда
shouldComponentUpdate
возвращает да, вы были уверены, что содержимое DOM действительно обновлено.Итак, версия здесь добавляет
componentDidUpdate
и становится:Виртуальный дом остается устаревшим, и, возможно, это не самый эффективный код, но, по крайней мере, он работает :) Моя ошибка устранена
Подробности:
1) Если вы поместите shouldComponentUpdate, чтобы избежать переходов курсора, то contenteditable никогда не будет перерисовываться (по крайней мере, при нажатии клавиш)
2) Если компонент никогда не перерисовывается при нажатии клавиши, то React сохраняет устаревшее виртуальное пространство для этого contenteditable.
3) Если React сохраняет устаревшую версию contenteditable в своем виртуальном dom-дереве, то если вы попытаетесь сбросить contenteditable до значения, устаревшего в виртуальном dom, то во время виртуального dom-diff React вычислит, что нет никаких изменений в обратиться в ДОМ!
В основном это происходит, когда:
источник
{...this.props}
чтобы клиент мог настроить это поведение извне,shouldComponentUpdate
код предотвращает скачки курсора?Это самое простое решение, которое сработало для меня.
источник
onInput
как указано в примере.Вероятно, это не совсем тот ответ, который вы ищете, но, борясь с этим сам и имея проблемы с предлагаемыми ответами, я решил вместо этого сделать его неконтролируемым.
Когда
editable
prop естьfalse
, я используюtext
prop как есть, но когда он естьtrue
, я переключаюсь в режим редактирования, в которомtext
нет никакого эффекта (но, по крайней мере, браузер не волнуется). За это времяonChange
производятся стрельбы по контролю. Наконец, когда яeditable
возвращаюсь кfalse
, он заполняет HTML тем, что было переданоtext
:источник
shouldComponentUpdate
так легко, поэтому даже это больше не спасает меня от переходов курсора. Наконец, у меня есть:empty:before
заполнители псевдоэлементов CSS, но этаshouldComponentUpdate
реализация помешала FF и Safari очистить поле, когда оно очищено пользователем. Мне потребовалось 5 часов, чтобы понять, что я могу обойти все эти проблемы с помощью неконтролируемого CE.editable
вUncontrolledContentEditable
. Не могли бы вы предоставить работоспособный пример?editable
извне. Подумайте о поле, которое можно редактировать в строке, когда пользователь нажимает «Изменить», и которое должно быть снова доступно только для чтения, когда пользователь нажимает «Сохранить» или «Отмена». Поэтому, когда он доступен только для чтения, я использую реквизиты, но перестаю смотреть на них всякий раз, когда вхожу в «режим редактирования», и снова смотрю на реквизиты только после выхода из него.escapeTextForBrowser
вescapeTextContentForBrowser
.Поскольку после завершения редактирования фокус элемента всегда теряется, вы можете просто использовать ловушку onBlur.
источник
Я предлагаю для этого использовать mutationObserver. Это дает вам больше контроля над происходящим. Он также дает вам более подробную информацию о том, как браузер интерпретирует все нажатия клавиш.
Здесь в TypeScript
источник
Вот компонент, который включает в себя многое из этого от lovasoa: https://github.com/lovasoa/react-contenteditable/blob/master/index.js
Он прокручивает событие в emitChange
Я успешно использую аналогичный подход
источник