แก้ไข 2015
มีคนทำโครงการเกี่ยวกับ NPM ด้วยวิธีแก้ปัญหาของฉัน: https://github.com/lovasoa/react-contenteditable
แก้ไข 06/2016:ฉันเพิ่งค้นพบปัญหาใหม่ที่เกิดขึ้นเมื่อเบราว์เซอร์พยายาม "ฟอร์แมต" html ที่คุณเพิ่งให้ไปซึ่งนำไปสู่การแสดงผลองค์ประกอบเสมอ ดู
แก้ไข 07/2016:นี่คือเนื้อหาการผลิตของฉันการใช้งานที่แก้ไขได้ มีตัวเลือกเพิ่มเติมบางอย่างreact-contenteditable
ที่คุณอาจต้องการ ได้แก่ :
- ล็อค
- API ที่จำเป็นซึ่งอนุญาตให้ฝังส่วนย่อย html
- ความสามารถในการฟอร์แมตเนื้อหา
สรุป:
วิธีแก้ปัญหาของ FakeRainBrigand ทำงานได้ดีสำหรับฉันมาระยะหนึ่งจนกระทั่งฉันได้รับปัญหาใหม่ ContentEditables เป็นความเจ็บปวดและไม่ใช่เรื่องง่ายที่จะจัดการกับ React ...
JSFiddleนี้แสดงให้เห็นถึงปัญหา
ดังที่คุณเห็นเมื่อคุณพิมพ์อักขระบางตัวและคลิกClear
เนื้อหาจะไม่ถูกล้าง นี่เป็นเพราะเราพยายามรีเซ็ต contenteditable เป็นค่า virtual dom ที่ทราบล่าสุด
ดูเหมือนว่า:
- คุณต้อง
shouldComponentUpdate
ป้องกันการกระโดดตำแหน่งคาเร็ต
- คุณไม่สามารถพึ่งพาอัลกอริทึมที่แตกต่างของ VDOM ของ React ได้หากคุณใช้
shouldComponentUpdate
วิธีนี้
ดังนั้นคุณต้องมีบรรทัดพิเศษเพื่อที่ว่าเมื่อใดก็ตามที่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;
}
});
Virtual Dom ยังคงล้าสมัยและอาจไม่ใช่รหัสที่มีประสิทธิภาพสูงสุด แต่อย่างน้อยก็ใช้งานได้ :) ข้อบกพร่องของฉันได้รับการแก้ไขแล้ว
รายละเอียด:
1) หากคุณใส่ shouldComponentUpdate เพื่อหลีกเลี่ยงการกระโดดของคาเร็ตเนื้อหาที่แก้ไขได้จะไม่ส่งกลับ (อย่างน้อยเมื่อกดแป้นพิมพ์)
2) หากคอมโพเนนต์ไม่แสดงผลในจังหวะสำคัญ React จะเก็บโดมเสมือนที่ล้าสมัยไว้สำหรับเนื้อหานี้ที่แก้ไขได้
3) หาก React เก็บเวอร์ชันที่ล้าสมัยของ contenteditable ไว้ใน virtual dom tree แล้วหากคุณพยายามรีเซ็ต contenteditable ให้เป็นค่าที่ล้าสมัยใน virtual dom แล้วในระหว่าง virtual dom ที่แตกต่างกัน React จะคำนวณว่าไม่มีการเปลี่ยนแปลงใด ๆ นำไปใช้กับ DOM!
สิ่งนี้เกิดขึ้นส่วนใหญ่เมื่อ:
- คุณมี contenteditable ที่ว่างเปล่าในตอนแรก (shouldComponentUpdate = true, prop = "", previous vdom = N / A),
- ผู้ใช้พิมพ์ข้อความบางส่วนและคุณป้องกันการแสดงผล (shouldComponentUpdate = false, prop = text, previous vdom = "")
- หลังจากที่ผู้ใช้คลิกปุ่มตรวจสอบความถูกต้องคุณต้องการเว้นช่องนั้น (shouldComponentUpdate = false, prop = "", previous vdom = "")
- เนื่องจากทั้ง vdom ที่ผลิตใหม่และรุ่นเก่าคือ "" จึงไม่สัมผัสกับโดม
initialValue
เข้าไปstate
และใช้ในrender
แต่ฉันจะไม่ปล่อยให้ตอบสนองการปรับปรุงมันต่อไป