Bagaimana cara mendengarkan perubahan acara untuk contentEditable
kontrol berbasis?
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
ke dalamstate
dan menggunakannya dalamrender
, tapi aku tidak membiarkan Bereaksi pembaruan lebih lanjut.contentEditable
mengubah pendekatan saya - alih-alihspan
atauparagraph
, saya telah menggunakaninput
bersama denganreadonly
atributnya.Jawaban:
Edit: Lihat jawaban Sebastien Lorber yang memperbaiki bug dalam implementasi saya.
Gunakan peristiwa onInput, dan secara opsional onBlur sebagai fallback. Anda mungkin ingin menyimpan konten sebelumnya untuk mencegah pengiriman acara tambahan.
Saya pribadi memiliki ini sebagai fungsi render saya.
jsbin
Yang menggunakan pembungkus sederhana ini di sekitar contentEditable.
sumber
this.setState({html: "something not in the editable div"}})
this.getDOMNode().innerHTML
masukshouldComponentUpdate
tidak terlalu dioptimalkan, benarstate.html
ke nilai "yang diketahui" terakhir, React tidak akan memperbarui DOM karena html baru persis sama sejauh menyangkut React (meskipun DOM sebenarnya berbeda). Lihat jsfiddle . Saya belum menemukan solusi yang baik untuk ini, jadi ide apa pun diterima.shouldComponentUpdate
harus murni (tidak memiliki efek samping).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: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:
shouldComponentUpdate
mencegah posisi sisipan melompatshouldComponentUpdate
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: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:
sumber
{...this.props}
sehingga klien dapat menyesuaikan perilaku ini dari luarshouldComponentUpdate
kode mencegah lompatan tanda sisipan?Ini adalah solusi paling sederhana yang berhasil untuk saya.
sumber
onInput
seperti yang dinyatakan dalam contoh.Ini mungkin bukan jawaban yang Anda cari, tetapi setelah berjuang dengan ini sendiri dan memiliki masalah dengan jawaban yang disarankan, saya memutuskan untuk membuatnya tidak terkendali.
Kapan
editable
propfalse
, saya menggunakantext
prop apa adanya, tetapi ketika itutrue
, saya beralih ke mode pengeditan yangtext
tidak berpengaruh (tapi setidaknya browser tidak panik). Selama inionChange
ditembakkan oleh kontrol. Akhirnya, ketika saya mengubahnyaeditable
kembali kefalse
, itu mengisi HTML dengan apa pun yang diteruskantext
:sumber
shouldComponentUpdate
dengan mudah sehingga bahkan tidak menyelamatkan saya dari lompatan tanda sisipan lagi. Akhirnya, saya memiliki:empty:before
placeholder pseudo-elemen CSS tetapishouldComponentUpdate
implementasi ini mencegah FF dan Safari membersihkan bidang ketika dihapus oleh pengguna. Butuh waktu 5 jam untuk menyadari bahwa saya dapat menghindari semua masalah ini dengan CE yang tidak terkontrol.editable
diUncontrolledContentEditable
. Bisakah Anda memberikan contoh yang dapat dijalankan?editable
dari luar. Pikirkan bidang yang dapat diedit secara inline ketika pengguna menekan "Edit" dan harus dibaca lagi ketika pengguna menekan "Simpan" atau "Batal". Jadi ketika itu hanya bisa dibaca, saya menggunakan alat peraga, tetapi saya berhenti melihatnya setiap kali saya masuk ke "mode edit" dan hanya melihat alat peraga lagi ketika saya keluar.escapeTextForBrowser
menjadiescapeTextContentForBrowser
.Karena ketika pengeditan selesai, fokus dari elemen selalu hilang, Anda cukup menggunakan hook onBlur.
sumber
Saya sarankan menggunakan mutationObserver untuk melakukan ini. Ini memberi Anda lebih banyak kendali atas apa yang sedang terjadi. Ini juga memberi Anda detail lebih lanjut tentang cara penelusuran menafsirkan semua penekanan tombol
Di sini, di TypeScript
sumber
Berikut adalah komponen yang menggabungkan banyak hal ini dengan lovasoa: https://github.com/lovasoa/react-contenteditable/blob/master/index.js
Dia menggeser acara di emitChange
Saya berhasil menggunakan pendekatan serupa
sumber