Chỉnh sửa 2015
Ai đó đã thực hiện một dự án về NPM với giải pháp của tôi: https://github.com/lovasoa/react-contentitable
Chỉnh sửa 06/2016: Tôi vừa phát hiện ra một vấn đề mới xảy ra khi trình duyệt cố gắng "định dạng lại" html mà bạn vừa đưa cho anh ta, dẫn đến thành phần luôn hiển thị lại. Xem
Chỉnh sửa 07/2016: đây là nội dung sản xuất của tôi Nó có một số tùy chọn bổ sung react-contenteditable
mà bạn có thể muốn, bao gồm:
- khóa
- API bắt buộc cho phép nhúng các đoạn html
- khả năng định dạng lại nội dung
Tóm lược:
Giải pháp của FakeRainBrigand đã hoạt động khá tốt đối với tôi trong một thời gian cho đến khi tôi gặp vấn đề mới. ContentEditables là một khó khăn và không thực sự dễ dàng để đối phó với React ...
JSFiddle này giải thích vấn đề.
Như bạn có thể thấy, khi bạn nhập một số ký tự và nhấp vào Clear
, nội dung sẽ không bị xóa. Điều này là do chúng tôi cố gắng đặt lại nội dung có thể thay đổi thành giá trị dom ảo cuối cùng đã biết.
Vì vậy, có vẻ như rằng:
- Bạn cần
shouldComponentUpdate
ngăn chặn nhảy vị trí dấu mũ
- Bạn không thể dựa vào thuật toán khác biệt VDOM của React nếu bạn sử dụng
shouldComponentUpdate
cách này.
Vì vậy, bạn cần thêm một dòng để bất cứ khi nào shouldComponentUpdate
trả về có, bạn chắc chắn rằng nội dung DOM đã thực sự được cập nhật.
Vì vậy, phiên bản ở đây thêm một componentDidUpdate
và trở thành:
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 ảo vẫn lỗi thời và nó có thể không phải là mã hiệu quả nhất, nhưng ít nhất nó vẫn hoạt động :) Lỗi của tôi đã được giải quyết
Chi tiết:
1) Nếu bạn đặt shouldComponentUpdate để tránh nhảy dấu mũ, thì nội dung có thể chỉnh sửa sẽ không bao giờ hiển thị (ít nhất là khi nhấn phím)
2) Nếu thành phần không bao giờ hiển thị trên hành trình phím, thì React sẽ giữ một dom ảo đã lỗi thời để có thể nội dung này.
3) Nếu React giữ một phiên bản lỗi thời của contenteditable trong cây dom ảo của nó, thì nếu bạn cố gắng đặt lại contenteditable thành giá trị đã lỗi thời trong dom ảo, thì trong quá trình khác biệt dom ảo, React sẽ tính toán rằng không có thay đổi nào đối với áp dụng cho DOM!
Điều này chủ yếu xảy ra khi:
- ban đầu bạn có một nội dung trống (nênComponentUpdate = true, prop = "", vdom trước đó = N / A),
- người dùng nhập một số văn bản và bạn ngăn kết xuất (shouldComponentUpdate = false, prop = text, vdom trước đó = "")
- sau khi người dùng nhấp vào nút xác thực, bạn muốn trống trường đó (shouldComponentUpdate = false, prop = "", vdom trước đó = "")
- vì cả vdom mới được sản xuất và cũ đều là "", React không chạm vào dom.
initialValue
vàostate
và sử dụng nórender
, nhưng tôi không để React cập nhật thêm.