Edit 2015
Seseorang telah membuat proyek di NPM dengan solusi saya: https://github.com/lovasoa/react-contenteditable
Sunting 06/2016: Saya baru saja mengenalkan masalah baru yang terjadi saat browser mencoba untuk "memformat ulang" html yang baru saja Anda berikan padanya, yang menyebabkan komponen selalu dirender ulang. Lihat
Sunting 07/2016: inilah implementasi contentEditable produksi saya. Ini memiliki beberapa opsi tambahan react-contenteditable
yang mungkin Anda inginkan, termasuk:
- penguncian
- API imperatif memungkinkan untuk menyematkan fragmen html
- kemampuan untuk memformat ulang konten
Ringkasan:
Solusi FakeRainBrigand telah bekerja dengan baik untuk saya selama beberapa waktu sampai saya mendapat masalah baru. ContentEditables memang menyebalkan, dan tidak mudah ditangani dengan React ...
JSFiddle ini menunjukkan masalahnya.
Seperti yang Anda lihat, saat Anda mengetik beberapa karakter dan mengkliknya Clear
, konten tidak dihapus. Ini karena kami mencoba menyetel ulang konten yang dapat diedit ke nilai dom virtual terakhir yang diketahui.
Jadi sepertinya:
- Anda perlu
shouldComponentUpdate
mencegah posisi sisipan melompat
- Anda tidak dapat mengandalkan algoritma perbedaan VDOM React jika Anda menggunakan
shouldComponentUpdate
cara ini.
Jadi, Anda memerlukan baris tambahan sehingga setiap kali shouldComponentUpdate
mengembalikan ya, Anda yakin konten DOM benar-benar diperbarui.
Jadi versi di sini menambahkan componentDidUpdate
dan menjadi:
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 virtual tetap ketinggalan zaman, dan ini mungkin bukan kode yang paling efisien, tetapi setidaknya berfungsi :) Bug saya teratasi
Rincian:
1) Jika Anda meletakkan shouldComponentUpdate untuk menghindari lompatan tanda sisipan, maka konten yang dapat diedit tidak pernah dirender (setidaknya pada penekanan tombol)
2) Jika komponen tidak pernah dirender pada penekanan tombol, maka React menyimpan dom virtual yang sudah ketinggalan zaman agar konten ini dapat diedit.
3) Jika React menyimpan versi lama dari konten yang dapat diedit di pohon dom virtualnya, maka jika Anda mencoba mengatur ulang konten yang dapat diedit ke nilai yang sudah ketinggalan zaman di dom virtual, maka selama perbedaan dom virtual, React akan menghitung bahwa tidak ada perubahan pada terapkan ke DOM!
Ini kebanyakan terjadi ketika:
- Anda memiliki konten kosong yang dapat diedit pada awalnya (shouldComponentUpdate = true, prop = "", vdom = N / A sebelumnya),
- pengguna mengetik beberapa teks dan Anda mencegah rendering (shouldComponentUpdate = false, prop = teks, vdom = "" sebelumnya)
- setelah pengguna mengklik tombol validasi, Anda ingin mengosongkan bidang itu (shouldComponentUpdate = false, prop = "", vdom sebelumnya = "")
- karena baik vdom yang baru diproduksi maupun yang lama adalah "", React tidak menyentuh dom.
initialValue
ke dalamstate
dan menggunakannya dalamrender
, tapi aku tidak membiarkan Bereaksi pembaruan lebih lanjut.