2015年を編集
誰かが私のソリューションを使用してNPMでプロジェクトを作成しました:https : //github.com/lovasoa/react-contenteditable
2016年6月編集:ブラウザーが提供したhtmlをブラウザーが「再フォーマット」しようとすると、コンポーネントが常に再レンダリングされるという新しい問題が発生しました。見る
2016年7月を編集:これが私のcontentcontentEditable実装です。それはreact-contenteditable
あなたが望むかもしれないことを含むいくつかの追加のオプションがあります:
- ロック
- HTMLフラグメントを埋め込むことができる命令型API
- コンテンツを再フォーマットする機能
概要:
FakeRainBrigandのソリューションは、新しい問題が発生するまでしばらくの間、問題なく機能しました。ContentEditablesは面倒で、Reactを扱うのは本当に簡単ではありません...
このJSFiddleは問題を示しています。
ご覧のとおり、一部の文字を入力してをクリックしてClear
も、コンテンツは消去されません。これは、contenteditableを最後の既知の仮想dom値にリセットしようとするためです。
だからそれはようです:
shouldComponentUpdate
キャレット位置のジャンプを防ぐ必要があります
shouldComponentUpdate
この方法を使用する場合、ReactのVDOM差分アルゴリズムに依存することはできません。
したがって、追加の行が必要になるので、shouldComponentUpdate
yesが返されるたびに、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;
}
});
仮想domは古いままで、最も効率的なコードではないかもしれませんが、少なくとも機能します:) 私のバグは解決されました
詳細:
1)キャレットジャンプを回避するためにshouldComponentUpdateを配置した場合、contenteditableは再レンダリングされません(少なくともキーストロークでは)
2)コンポーネントがキーストロークで再レンダリングされない場合、Reactはこのcontenteditableの古い仮想domを保持します。
3)Reactが仮想domツリーでcontenteditableの古いバージョンを保持している場合、contenteditableを仮想domで古くなった値にリセットしようとすると、仮想dom diff中に、Reactは変更がないことを計算しますDOMに適用してください!
これは主に次の場合に発生します。
- 最初に空のcontenteditableがある(shouldComponentUpdate = true、prop = ""、前のvdom = N / A)、
- ユーザーがテキストを入力し、レンダリングを禁止します(shouldComponentUpdate = false、prop = text、previous vdom = "")
- ユーザーが検証ボタンをクリックした後、そのフィールドを空にしたい(shouldComponentUpdate = false、prop = ""、previous vdom = "")
- 新しく作成されたvdomと古いvdomはどちらも「」であるため、Reactはdomに触れません。
initialValue
てstate
使用しましたがrender
、Reactにそれ以上更新させません。